1 /*
2 * Copyright (C) 2021 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_view_function.h"
18 #include <cstddef>
19 #include <string>
20 #include <utility>
21
22 #include "perfetto/base/status.h"
23 #include "perfetto/ext/base/string_utils.h"
24 #include "perfetto/ext/base/string_view.h"
25 #include "perfetto/trace_processor/basic_types.h"
26 #include "src/trace_processor/containers/null_term_string_view.h"
27 #include "src/trace_processor/perfetto_sql/engine/perfetto_sql_engine.h"
28 #include "src/trace_processor/perfetto_sql/parser/function_util.h"
29 #include "src/trace_processor/sqlite/sql_source.h"
30 #include "src/trace_processor/sqlite/sqlite_utils.h"
31 #include "src/trace_processor/util/status_macros.h"
32
33 namespace perfetto::trace_processor {
34
Run(CreateViewFunction::Context * ctx,size_t argc,sqlite3_value ** argv,SqlValue &,Destructors &)35 base::Status CreateViewFunction::Run(CreateViewFunction::Context* ctx,
36 size_t argc,
37 sqlite3_value** argv,
38 SqlValue&,
39 Destructors&) {
40 if (argc != 3) {
41 return base::ErrStatus(
42 "CREATE_VIEW_FUNCTION: invalid number of args; expected %u, received "
43 "%zu",
44 3u, argc);
45 }
46
47 sqlite3_value* prototype_value = argv[0];
48 sqlite3_value* return_prototype_value = argv[1];
49 sqlite3_value* sql_defn_value = argv[2];
50
51 // Type check all the arguments.
52 {
53 auto type_check = [prototype_value](sqlite3_value* value,
54 SqlValue::Type type, const char* desc) {
55 base::Status status = sqlite::utils::TypeCheckSqliteValue(value, type);
56 if (!status.ok()) {
57 return base::ErrStatus("CREATE_VIEW_FUNCTION[prototype=%s]: %s %s",
58 sqlite3_value_text(prototype_value), desc,
59 status.c_message());
60 }
61 return base::OkStatus();
62 };
63
64 RETURN_IF_ERROR(type_check(prototype_value, SqlValue::Type::kString,
65 "function prototype (first argument)"));
66 RETURN_IF_ERROR(type_check(return_prototype_value, SqlValue::Type::kString,
67 "return prototype (second argument)"));
68 RETURN_IF_ERROR(type_check(sql_defn_value, SqlValue::Type::kString,
69 "SQL definition (third argument)"));
70 }
71
72 // Extract the arguments from the value wrappers.
73 auto extract_string = [](sqlite3_value* value) -> const char* {
74 return reinterpret_cast<const char*>(sqlite3_value_text(value));
75 };
76
77 const char* prototype_str = extract_string(prototype_value);
78 const char* return_prototype_str = extract_string(return_prototype_value);
79 const char* sql_defn_str = extract_string(sql_defn_value);
80
81 static constexpr char kSqlTemplate[] =
82 R"""(CREATE OR REPLACE PERFETTO FUNCTION %s RETURNS TABLE(%s) AS %s;)""";
83
84 base::StringView function_name;
85 RETURN_IF_ERROR(ParseFunctionName(prototype_str, function_name));
86
87 std::string function_name_str = function_name.ToStdString();
88
89 NullTermStringView sql_defn(sql_defn_str);
90 std::string formatted_sql(sql_defn.size() + 1024, '\0');
91 size_t size = base::SprintfTrunc(formatted_sql.data(), formatted_sql.size(),
92 kSqlTemplate, prototype_str,
93 return_prototype_str, sql_defn_str);
94 formatted_sql.resize(size);
95
96 auto res = ctx->Execute(
97 SqlSource::FromTraceProcessorImplementation(std::move(formatted_sql)));
98 return res.status();
99 }
100
101 } // namespace perfetto::trace_processor
102