• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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