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/scoped_db.h"
27 #include "src/trace_processor/sqlite/sql_source.h"
28 #include "src/trace_processor/sqlite/sqlite_engine.h"
29 #include "src/trace_processor/sqlite/sqlite_utils.h"
30 #include "src/trace_processor/tp_metatrace.h"
31 #include "src/trace_processor/util/status_macros.h"
32 
33 namespace perfetto {
34 namespace trace_processor {
35 
Run(PerfettoSqlEngine * engine,size_t argc,sqlite3_value ** argv,SqlValue &,Destructors &)36 base::Status CreateFunction::Run(PerfettoSqlEngine* engine,
37                                  size_t argc,
38                                  sqlite3_value** argv,
39                                  SqlValue&,
40                                  Destructors&) {
41   RETURN_IF_ERROR(sqlite::utils::CheckArgCount("CREATE_FUNCTION", argc, 3u));
42 
43   sqlite3_value* prototype_value = argv[0];
44   sqlite3_value* return_type_value = argv[1];
45   sqlite3_value* sql_defn_value = argv[2];
46 
47   // Type check all the arguments.
48   {
49     auto type_check = [prototype_value](sqlite3_value* value,
50                                         SqlValue::Type type, const char* desc) {
51       base::Status status = sqlite::utils::TypeCheckSqliteValue(value, type);
52       if (!status.ok()) {
53         return base::ErrStatus("CREATE_FUNCTION[prototype=%s]: %s %s",
54                                sqlite3_value_text(prototype_value), desc,
55                                status.c_message());
56       }
57       return base::OkStatus();
58     };
59 
60     RETURN_IF_ERROR(type_check(prototype_value, SqlValue::Type::kString,
61                                "function prototype (first argument)"));
62     RETURN_IF_ERROR(type_check(return_type_value, SqlValue::Type::kString,
63                                "return type (second argument)"));
64     RETURN_IF_ERROR(type_check(sql_defn_value, SqlValue::Type::kString,
65                                "SQL definition (third argument)"));
66   }
67 
68   // Extract the arguments from the value wrappers.
69   auto extract_string = [](sqlite3_value* value) -> base::StringView {
70     return reinterpret_cast<const char*>(sqlite3_value_text(value));
71   };
72   std::string prototype_str = extract_string(prototype_value).ToStdString();
73   std::string return_type_str = extract_string(return_type_value).ToStdString();
74   std::string sql_defn_str = extract_string(sql_defn_value).ToStdString();
75 
76   FunctionPrototype prototype;
77   RETURN_IF_ERROR(ParsePrototype(base::StringView(prototype_str), prototype));
78   return engine->RegisterRuntimeFunction(
79       true /* replace */, prototype, return_type_str,
80       SqlSource::FromTraceProcessorImplementation(std::move(sql_defn_str)));
81 }
82 
Run(PerfettoSqlEngine * engine,size_t argc,sqlite3_value ** argv,SqlValue &,Destructors &)83 base::Status ExperimentalMemoize::Run(PerfettoSqlEngine* engine,
84                                       size_t argc,
85                                       sqlite3_value** argv,
86                                       SqlValue&,
87                                       Destructors&) {
88   RETURN_IF_ERROR(
89       sqlite::utils::CheckArgCount("EXPERIMENTAL_MEMOIZE", argc, 1));
90   base::StatusOr<std::string> function_name =
91       sqlite::utils::ExtractStringArg("MEMOIZE", "function_name", argv[0]);
92   RETURN_IF_ERROR(function_name.status());
93   return engine->EnableSqlFunctionMemoization(*function_name);
94 }
95 
96 }  // namespace trace_processor
97 }  // namespace perfetto
98