• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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/sqlite/sqlite_utils.h"
18 #include <bitset>
19 #include <sstream>
20 #include "perfetto/base/status.h"
21 
22 namespace perfetto {
23 namespace trace_processor {
24 namespace sqlite_utils {
25 namespace internal {
26 namespace {
ToExpectedTypesString(ExpectedTypesSet expected_types)27 std::string ToExpectedTypesString(ExpectedTypesSet expected_types) {
28   PERFETTO_CHECK(expected_types.any());
29   std::stringstream ss;
30   if (expected_types.count() > 1) {
31     ss << "any of ";
32   }
33 
34   bool add_separator = false;
35   for (size_t i = 0; i < expected_types.size(); ++i) {
36     if (expected_types[i]) {
37       ss << (add_separator ? ", " : "")
38          << SqliteTypeToFriendlyString(static_cast<SqlValue::Type>(i));
39       add_separator = true;
40     }
41   }
42 
43   return ss.str();
44 }
45 }  // namespace
46 
InvalidArgumentTypeError(const char * argument_name,size_t arg_index,SqlValue::Type actual_type,ExpectedTypesSet expected_types)47 base::Status InvalidArgumentTypeError(const char* argument_name,
48                                       size_t arg_index,
49                                       SqlValue::Type actual_type,
50                                       ExpectedTypesSet expected_types) {
51   return ToInvalidArgumentError(
52       argument_name, arg_index,
53       base::ErrStatus("does not have expected type. Expected %s but found %s",
54                       ToExpectedTypesString(expected_types).c_str(),
55                       SqliteTypeToFriendlyString(actual_type)));
56 }
57 
ExtractArgument(size_t argc,sqlite3_value ** argv,const char * argument_name,size_t arg_index,ExpectedTypesSet expected_types)58 base::StatusOr<SqlValue> ExtractArgument(size_t argc,
59                                          sqlite3_value** argv,
60                                          const char* argument_name,
61                                          size_t arg_index,
62                                          ExpectedTypesSet expected_types) {
63   if (arg_index >= argc) {
64     return MissingArgumentError(argument_name);
65   }
66 
67   SqlValue value = sqlite_utils::SqliteValueToSqlValue(argv[arg_index]);
68 
69   if (!expected_types.test(value.type)) {
70     return InvalidArgumentTypeError(argument_name, arg_index, value.type,
71                                     expected_types);
72   }
73 
74   return std::move(value);
75 }
76 }  // namespace internal
77 
SqliteValueToWString(sqlite3_value * value)78 std::wstring SqliteValueToWString(sqlite3_value* value) {
79   PERFETTO_CHECK(sqlite3_value_type(value) == SQLITE_TEXT);
80   int len = sqlite3_value_bytes16(value);
81   PERFETTO_CHECK(len >= 0);
82   size_t count = static_cast<size_t>(len) / sizeof(wchar_t);
83   return std::wstring(
84       reinterpret_cast<const wchar_t*>(sqlite3_value_text16(value)), count);
85 }
86 
GetColumnsForTable(sqlite3 * db,const std::string & raw_table_name,std::vector<SqliteTable::Column> & columns)87 base::Status GetColumnsForTable(sqlite3* db,
88                                 const std::string& raw_table_name,
89                                 std::vector<SqliteTable::Column>& columns) {
90   PERFETTO_DCHECK(columns.empty());
91   char sql[1024];
92   const char kRawSql[] = "SELECT name, type from pragma_table_info(\"%s\")";
93 
94   // Support names which are table valued functions with arguments.
95   std::string table_name = raw_table_name.substr(0, raw_table_name.find('('));
96   size_t n = base::SprintfTrunc(sql, sizeof(sql), kRawSql, table_name.c_str());
97   PERFETTO_DCHECK(n > 0);
98 
99   sqlite3_stmt* raw_stmt = nullptr;
100   int err =
101       sqlite3_prepare_v2(db, sql, static_cast<int>(n), &raw_stmt, nullptr);
102   if (err != SQLITE_OK) {
103     return base::ErrStatus("Preparing database failed");
104   }
105   ScopedStmt stmt(raw_stmt);
106   PERFETTO_DCHECK(sqlite3_column_count(*stmt) == 2);
107 
108   for (;;) {
109     err = sqlite3_step(raw_stmt);
110     if (err == SQLITE_DONE)
111       break;
112     if (err != SQLITE_ROW) {
113       return base::ErrStatus("Querying schema of table %s failed",
114                              raw_table_name.c_str());
115     }
116 
117     const char* name =
118         reinterpret_cast<const char*>(sqlite3_column_text(*stmt, 0));
119     const char* raw_type =
120         reinterpret_cast<const char*>(sqlite3_column_text(*stmt, 1));
121     if (!name || !raw_type || !*name) {
122       return base::ErrStatus("Schema for %s has invalid column values",
123                              raw_table_name.c_str());
124     }
125 
126     SqlValue::Type type;
127     if (base::CaseInsensitiveEqual(raw_type, "STRING") ||
128         base::CaseInsensitiveEqual(raw_type, "TEXT")) {
129       type = SqlValue::Type::kString;
130     } else if (base::CaseInsensitiveEqual(raw_type, "DOUBLE")) {
131       type = SqlValue::Type::kDouble;
132     } else if (base::CaseInsensitiveEqual(raw_type, "BIG INT") ||
133                base::CaseInsensitiveEqual(raw_type, "BIGINT") ||
134                base::CaseInsensitiveEqual(raw_type, "UNSIGNED INT") ||
135                base::CaseInsensitiveEqual(raw_type, "INT") ||
136                base::CaseInsensitiveEqual(raw_type, "BOOLEAN") ||
137                base::CaseInsensitiveEqual(raw_type, "INTEGER")) {
138       type = SqlValue::Type::kLong;
139     } else if (!*raw_type) {
140       PERFETTO_DLOG("Unknown column type for %s %s", raw_table_name.c_str(),
141                     name);
142       type = SqlValue::Type::kNull;
143     } else {
144       return base::ErrStatus("Unknown column type '%s' on table %s", raw_type,
145                              raw_table_name.c_str());
146     }
147     columns.emplace_back(columns.size(), name, type);
148   }
149 
150   // Catch mis-spelt table names.
151   //
152   // A SELECT on pragma_table_info() returns no rows if the
153   // table that was queried is not present.
154   if (columns.empty()) {
155     return base::ErrStatus("Unknown table or view name '%s'",
156                            raw_table_name.c_str());
157   }
158 
159   return base::OkStatus();
160 }
161 
SqliteTypeToFriendlyString(SqlValue::Type type)162 const char* SqliteTypeToFriendlyString(SqlValue::Type type) {
163   switch (type) {
164     case SqlValue::Type::kNull:
165       return "NULL";
166     case SqlValue::Type::kLong:
167       return "BOOL/INT/UINT/LONG";
168     case SqlValue::Type::kDouble:
169       return "FLOAT/DOUBLE";
170     case SqlValue::Type::kString:
171       return "STRING";
172     case SqlValue::Type::kBytes:
173       return "BYTES/PROTO";
174   }
175   PERFETTO_FATAL("For GCC");
176 }
177 
TypeCheckSqliteValue(sqlite3_value * value,SqlValue::Type expected_type)178 base::Status TypeCheckSqliteValue(sqlite3_value* value,
179                                   SqlValue::Type expected_type) {
180   return TypeCheckSqliteValue(value, expected_type,
181                               SqliteTypeToFriendlyString(expected_type));
182 }
183 
TypeCheckSqliteValue(sqlite3_value * value,SqlValue::Type expected_type,const char * expected_type_str)184 base::Status TypeCheckSqliteValue(sqlite3_value* value,
185                                   SqlValue::Type expected_type,
186                                   const char* expected_type_str) {
187   SqlValue::Type actual_type =
188       sqlite_utils::SqliteTypeToSqlValueType(sqlite3_value_type(value));
189   if (actual_type != SqlValue::Type::kNull && actual_type != expected_type) {
190     return base::ErrStatus(
191         "does not have expected type: expected %s, actual %s",
192         expected_type_str, SqliteTypeToFriendlyString(actual_type));
193   }
194   return base::OkStatus();
195 }
196 
197 template <typename T>
ExtractFromSqlValueInt(const SqlValue & value,std::optional<T> & out)198 base::Status ExtractFromSqlValueInt(const SqlValue& value,
199                                     std::optional<T>& out) {
200   if (value.is_null()) {
201     out = std::nullopt;
202     return base::OkStatus();
203   }
204   if (value.type != SqlValue::kLong) {
205     return base::ErrStatus(
206         "value has type %s which does not match the expected type %s",
207         SqliteTypeToFriendlyString(value.type),
208         SqliteTypeToFriendlyString(SqlValue::kLong));
209   }
210 
211   int64_t res = value.AsLong();
212   if (res > std::numeric_limits<T>::max() ||
213       res < std::numeric_limits<T>::min()) {
214     return base::ErrStatus("value %ld does not fit inside the range [%ld, %ld]",
215                            static_cast<long>(res),
216                            static_cast<long>(std::numeric_limits<T>::min()),
217                            static_cast<long>(std::numeric_limits<T>::max()));
218   }
219   out = static_cast<T>(res);
220   return base::OkStatus();
221 }
222 
ExtractFromSqlValue(const SqlValue & value,std::optional<int64_t> & out)223 base::Status ExtractFromSqlValue(const SqlValue& value,
224                                  std::optional<int64_t>& out) {
225   return ExtractFromSqlValueInt(value, out);
226 }
ExtractFromSqlValue(const SqlValue & value,std::optional<int32_t> & out)227 base::Status ExtractFromSqlValue(const SqlValue& value,
228                                  std::optional<int32_t>& out) {
229   return ExtractFromSqlValueInt(value, out);
230 }
ExtractFromSqlValue(const SqlValue & value,std::optional<uint32_t> & out)231 base::Status ExtractFromSqlValue(const SqlValue& value,
232                                  std::optional<uint32_t>& out) {
233   return ExtractFromSqlValueInt(value, out);
234 }
ExtractFromSqlValue(const SqlValue & value,std::optional<double> & out)235 base::Status ExtractFromSqlValue(const SqlValue& value,
236                                  std::optional<double>& out) {
237   if (value.is_null()) {
238     out = std::nullopt;
239     return base::OkStatus();
240   }
241   if (value.type != SqlValue::kDouble) {
242     return base::ErrStatus(
243         "value has type %s which does not match the expected type %s",
244         SqliteTypeToFriendlyString(value.type),
245         SqliteTypeToFriendlyString(SqlValue::kDouble));
246   }
247   out = value.AsDouble();
248   return base::OkStatus();
249 }
ExtractFromSqlValue(const SqlValue & value,std::optional<const char * > & out)250 base::Status ExtractFromSqlValue(const SqlValue& value,
251                                  std::optional<const char*>& out) {
252   if (value.is_null()) {
253     out = std::nullopt;
254     return base::OkStatus();
255   }
256   if (value.type != SqlValue::kString) {
257     return base::ErrStatus(
258         "value has type %s which does not match the expected type %s",
259         SqliteTypeToFriendlyString(value.type),
260         SqliteTypeToFriendlyString(SqlValue::kString));
261   }
262   out = value.AsString();
263   return base::OkStatus();
264 }
265 
MissingArgumentError(const char * argument_name)266 base::Status MissingArgumentError(const char* argument_name) {
267   return base::ErrStatus("argument missing: %s", argument_name);
268 }
269 
ToInvalidArgumentError(const char * argument_name,size_t arg_index,const base::Status error)270 base::Status ToInvalidArgumentError(const char* argument_name,
271                                     size_t arg_index,
272                                     const base::Status error) {
273   return base::ErrStatus("argument %s at pos %zu: %s", argument_name,
274                          arg_index + 1, error.message().c_str());
275 }
276 
277 }  // namespace sqlite_utils
278 }  // namespace trace_processor
279 }  // namespace perfetto
280