xref: /aosp_15_r20/external/perfetto/src/trace_processor/sqlite/sqlite_utils.h (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1 /*
2  * Copyright (C) 2018 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 #ifndef SRC_TRACE_PROCESSOR_SQLITE_SQLITE_UTILS_H_
18 #define SRC_TRACE_PROCESSOR_SQLITE_SQLITE_UTILS_H_
19 
20 #include <sqlite3.h>
21 #include <bitset>
22 #include <cstddef>
23 #include <cstdint>
24 #include <cstring>
25 #include <functional>
26 #include <optional>
27 #include <string>
28 #include <utility>
29 #include <vector>
30 
31 #include "perfetto/base/logging.h"
32 #include "perfetto/base/status.h"
33 #include "perfetto/ext/base/status_or.h"
34 #include "perfetto/trace_processor/basic_types.h"
35 #include "src/trace_processor/sqlite/bindings/sqlite_result.h"
36 
37 // Analogous to ASSIGN_OR_RETURN macro. Returns an sqlite error.
38 #define SQLITE_RETURN_IF_ERROR(vtab, expr)                                  \
39   do {                                                                      \
40     const base::Status& status_macro_internal_status = (expr);              \
41     if (!status_macro_internal_status.ok())                                 \
42       return sqlite::utils::SetError((vtab), status_macro_internal_status); \
43   } while (0)
44 
45 // Analogous to ASSIGN_OR_RETURN macro. Returns an sqlite error.
46 #define SQLITE_ASSIGN_OR_RETURN(vtab, lhs, rhs)                            \
47   PERFETTO_INTERNAL_MACRO_CONCAT(auto status_or, __LINE__) = rhs;          \
48   SQLITE_RETURN_IF_ERROR(                                                  \
49       vtab, PERFETTO_INTERNAL_MACRO_CONCAT(status_or, __LINE__).status()); \
50   lhs = std::move(PERFETTO_INTERNAL_MACRO_CONCAT(status_or, __LINE__).value())
51 
52 namespace perfetto::trace_processor::sqlite::utils {
53 
54 const auto kSqliteStatic = reinterpret_cast<sqlite3_destructor_type>(0);
55 const auto kSqliteTransient = reinterpret_cast<sqlite3_destructor_type>(-1);
56 
IsOpEq(int op)57 inline bool IsOpEq(int op) {
58   return op == SQLITE_INDEX_CONSTRAINT_EQ;
59 }
IsOpLe(int op)60 inline bool IsOpLe(int op) {
61   return op == SQLITE_INDEX_CONSTRAINT_LE;
62 }
IsOpLt(int op)63 inline bool IsOpLt(int op) {
64   return op == SQLITE_INDEX_CONSTRAINT_LT;
65 }
IsOpGe(int op)66 inline bool IsOpGe(int op) {
67   return op == SQLITE_INDEX_CONSTRAINT_GE;
68 }
IsOpGt(int op)69 inline bool IsOpGt(int op) {
70   return op == SQLITE_INDEX_CONSTRAINT_GT;
71 }
72 
SqliteTypeToSqlValueType(int sqlite_type)73 inline SqlValue::Type SqliteTypeToSqlValueType(int sqlite_type) {
74   switch (sqlite_type) {
75     case SQLITE_NULL:
76       return SqlValue::Type::kNull;
77     case SQLITE_BLOB:
78       return SqlValue::Type::kBytes;
79     case SQLITE_INTEGER:
80       return SqlValue::Type::kLong;
81     case SQLITE_FLOAT:
82       return SqlValue::Type::kDouble;
83     case SQLITE_TEXT:
84       return SqlValue::Type::kString;
85   }
86   PERFETTO_FATAL("Unknown SQLite type %d", sqlite_type);
87 }
88 
SqliteValueToSqlValue(sqlite3_value * value)89 inline SqlValue SqliteValueToSqlValue(sqlite3_value* value) {
90   SqlValue sql_value;
91   switch (sqlite3_value_type(value)) {
92     case SQLITE_INTEGER:
93       sql_value.type = SqlValue::Type::kLong;
94       sql_value.long_value = sqlite3_value_int64(value);
95       break;
96     case SQLITE_FLOAT:
97       sql_value.type = SqlValue::Type::kDouble;
98       sql_value.double_value = sqlite3_value_double(value);
99       break;
100     case SQLITE_TEXT:
101       sql_value.type = SqlValue::Type::kString;
102       sql_value.string_value =
103           reinterpret_cast<const char*>(sqlite3_value_text(value));
104       break;
105     case SQLITE_BLOB:
106       sql_value.type = SqlValue::Type::kBytes;
107       sql_value.bytes_value = sqlite3_value_blob(value);
108       sql_value.bytes_count = static_cast<size_t>(sqlite3_value_bytes(value));
109       break;
110   }
111   return sql_value;
112 }
113 
SqlValueToString(SqlValue value)114 inline std::optional<std::string> SqlValueToString(SqlValue value) {
115   switch (value.type) {
116     case SqlValue::Type::kString:
117       return value.AsString();
118     case SqlValue::Type::kDouble:
119       return std::to_string(value.AsDouble());
120     case SqlValue::Type::kLong:
121       return std::to_string(value.AsLong());
122     case SqlValue::Type::kBytes:
123     case SqlValue::Type::kNull:
124       return std::nullopt;
125   }
126   PERFETTO_FATAL("For GCC");
127 }
128 
129 inline void ReportSqlValue(
130     sqlite3_context* ctx,
131     const SqlValue& value,
132     sqlite3_destructor_type string_destructor = kSqliteTransient,
133     sqlite3_destructor_type bytes_destructor = kSqliteTransient) {
134   switch (value.type) {
135     case SqlValue::Type::kLong:
136       sqlite::result::Long(ctx, value.long_value);
137       break;
138     case SqlValue::Type::kDouble:
139       sqlite::result::Double(ctx, value.double_value);
140       break;
141     case SqlValue::Type::kString: {
142       sqlite::result::RawString(ctx, value.string_value, string_destructor);
143       break;
144     }
145     case SqlValue::Type::kBytes:
146       sqlite::result::RawBytes(ctx, value.bytes_value,
147                                static_cast<int>(value.bytes_count),
148                                bytes_destructor);
149       break;
150     case SqlValue::Type::kNull:
151       sqlite::result::Null(ctx);
152       break;
153   }
154 }
155 
SetError(sqlite3_vtab * tab,const char * status)156 inline int SetError(sqlite3_vtab* tab, const char* status) {
157   sqlite3_free(tab->zErrMsg);
158   tab->zErrMsg = sqlite3_mprintf("%s", status);
159   return SQLITE_ERROR;
160 }
161 
SetError(sqlite3_context * ctx,const char * status)162 inline void SetError(sqlite3_context* ctx, const char* status) {
163   sqlite::result::Error(ctx, status);
164 }
165 
SetError(sqlite3_vtab * tab,base::Status s)166 inline int SetError(sqlite3_vtab* tab, base::Status s) {
167   return SetError(tab, s.c_message());
168 }
169 
SetError(sqlite3_context * ctx,const base::Status & status)170 inline void SetError(sqlite3_context* ctx, const base::Status& status) {
171   PERFETTO_CHECK(!status.ok());
172   sqlite::result::Error(ctx, status.c_message());
173 }
174 
SetError(sqlite3_context * ctx,const std::string & function_name,const base::Status & status)175 inline void SetError(sqlite3_context* ctx,
176                      const std::string& function_name,
177                      const base::Status& status) {
178   SetError(ctx, base::ErrStatus("%s: %s", function_name.c_str(),
179                                 status.c_message()));
180 }
181 
182 // For a given |sqlite3_index_info| struct received in a BestIndex call, returns
183 // whether all |arg_count| arguments (with |is_arg_column| indicating whether a
184 // given column is a function argument) have exactly one equality constraint
185 // associated with them.
186 //
187 // If so, the associated constraint is omitted and the argvIndex is mapped to
188 // the corresponding argument's index.
ValidateFunctionArguments(sqlite3_index_info * info,size_t arg_count,const std::function<bool (size_t)> & is_arg_column)189 inline base::Status ValidateFunctionArguments(
190     sqlite3_index_info* info,
191     size_t arg_count,
192     const std::function<bool(size_t)>& is_arg_column) {
193   std::vector<bool> present;
194   size_t present_count = 0;
195   for (int i = 0; i < info->nConstraint; ++i) {
196     const auto& in = info->aConstraint[i];
197     if (!in.usable) {
198       continue;
199     }
200     auto cs_col = static_cast<size_t>(in.iColumn);
201     if (!is_arg_column(cs_col)) {
202       continue;
203     }
204     if (!IsOpEq(in.op)) {
205       return base::ErrStatus(
206           "Unexpected non equality constraints for column %zu", cs_col);
207     }
208     if (cs_col >= present.size()) {
209       present.resize(cs_col + 1);
210     }
211     if (present[cs_col]) {
212       return base::ErrStatus("Unexpected multiple constraints for column %zu",
213                              cs_col);
214     }
215     present[cs_col] = true;
216     present_count++;
217 
218     auto& out = info->aConstraintUsage[i];
219     out.argvIndex = static_cast<int>(present_count);
220     out.omit = true;
221   }
222   if (present_count != arg_count) {
223     return base::ErrStatus(
224         "Unexpected missing argument: expected %zu, actual %zu", arg_count,
225         present_count);
226   }
227   return base::OkStatus();
228 }
229 
SqlValueTypeToString(SqlValue::Type type)230 inline const char* SqlValueTypeToString(SqlValue::Type type) {
231   switch (type) {
232     case SqlValue::Type::kString:
233       return "STRING";
234     case SqlValue::Type::kDouble:
235       return "DOUBLE";
236     case SqlValue::Type::kLong:
237       return "LONG";
238     case SqlValue::Type::kBytes:
239       return "BYTES";
240     case SqlValue::Type::kNull:
241       return "NULL";
242   }
243   PERFETTO_FATAL("For GCC");
244 }
245 
246 // Converts the given SqlValue type to the type string SQLite understands.
SqlValueTypeToSqliteTypeName(SqlValue::Type type)247 inline std::string SqlValueTypeToSqliteTypeName(SqlValue::Type type) {
248   switch (type) {
249     case SqlValue::Type::kString:
250       return "TEXT";
251     case SqlValue::Type::kLong:
252       return "BIGINT";
253     case SqlValue::Type::kDouble:
254       return "DOUBLE";
255     case SqlValue::Type::kBytes:
256       return "BLOB";
257     case SqlValue::Type::kNull:
258       // Default to BIGINT for columns which contains only NULLs - if we don't
259       // specify the type, sqlite will default to BLOB, which is going to trip
260       // a number of various checks.
261       return "BIGINT";
262   }
263   PERFETTO_FATAL("Not reached");  // For gcc
264 }
265 
266 // Exracts the given type from the SqlValue if |value| can fit
267 // in the provided optional. Note that SqlValue::kNull will always
268 // succeed and cause std::nullopt to be set.
269 //
270 // Returns base::ErrStatus if the type does not match or does not
271 // fit in the width of the provided optional type (i.e. int64 value
272 // not fitting in int32 optional).
273 base::Status ExtractFromSqlValue(const SqlValue& value,
274                                  std::optional<int64_t>&);
275 base::Status ExtractFromSqlValue(const SqlValue& value,
276                                  std::optional<int32_t>&);
277 base::Status ExtractFromSqlValue(const SqlValue& value,
278                                  std::optional<uint32_t>&);
279 base::Status ExtractFromSqlValue(const SqlValue& value, std::optional<double>&);
280 base::Status ExtractFromSqlValue(const SqlValue& value,
281                                  std::optional<const char*>&);
282 
283 // Returns the column names for the table named by |raw_table_name|.
284 base::Status GetColumnsForTable(
285     sqlite3* db,
286     const std::string& raw_table_name,
287     std::vector<std::pair<SqlValue::Type, std::string>>& columns);
288 
289 // Reads a `SQLITE_TEXT` value and returns it as a wstring (UTF-16) in the
290 // default byte order. `value` must be a `SQLITE_TEXT`.
291 std::wstring SqliteValueToWString(sqlite3_value* value);
292 
293 // Given an SqlValue::Type, converts it to a human-readable string.
294 // This should really only be used for debugging messages.
295 const char* SqliteTypeToFriendlyString(SqlValue::Type type);
296 
297 // Verifies if |argc| matches |expected_argc| and returns an appropriate error
298 // message if they don't match.
299 base::Status CheckArgCount(const char* function_name,
300                            size_t argc,
301                            size_t expected_argc);
302 
303 // Type-safe helpers to extract an arg value from a sqlite3_value*, returning an
304 // appropriate message if it fails.
305 base::StatusOr<int64_t> ExtractIntArg(const char* function_name,
306                                       const char* arg_name,
307                                       sqlite3_value* value);
308 base::StatusOr<double> ExtractDoubleArg(const char* function_name,
309                                         const char* arg_name,
310                                         sqlite3_value* value);
311 base::StatusOr<std::string> ExtractStringArg(const char* function_name,
312                                              const char* arg_name,
313                                              sqlite3_value* value);
314 
315 // Verifies if |value| has the type represented by |expected_type|.
316 // Returns base::OkStatus if it does or an base::ErrStatus with an
317 // appropriate error mesage (incorporating |expected_type_str| if specified).
318 base::Status TypeCheckSqliteValue(sqlite3_value* value,
319                                   SqlValue::Type expected_type);
320 base::Status TypeCheckSqliteValue(sqlite3_value* value,
321                                   SqlValue::Type expected_type,
322                                   const char* expected_type_str);
323 
324 namespace internal {
325 
326 static_assert(sizeof(size_t) * 8 > SqlValue::kLastType);
327 using ExpectedTypesSet = std::bitset<SqlValue::kLastType + 1>;
328 
329 template <typename... args>
ToExpectedTypesSet(args...expected_type_args)330 constexpr ExpectedTypesSet ToExpectedTypesSet(args... expected_type_args) {
331   ExpectedTypesSet set;
332   for (const SqlValue::Type t : {expected_type_args...}) {
333     set.set(static_cast<size_t>(t));
334   }
335   return set;
336 }
337 
338 base::StatusOr<SqlValue> ExtractArgument(size_t argc,
339                                          sqlite3_value** argv,
340                                          const char* argument_name,
341                                          size_t arg_index,
342                                          ExpectedTypesSet expected_types);
343 base::Status InvalidArgumentTypeError(const char* argument_name,
344                                       size_t arg_index,
345                                       SqlValue::Type actual_type,
346                                       ExpectedTypesSet expected_types);
347 }  // namespace internal
348 
349 template <typename... args>
InvalidArgumentTypeError(const char * argument_name,size_t arg_index,SqlValue::Type actual_type,SqlValue::Type expected_type,args...expected_type_args)350 base::Status InvalidArgumentTypeError(const char* argument_name,
351                                       size_t arg_index,
352                                       SqlValue::Type actual_type,
353                                       SqlValue::Type expected_type,
354                                       args... expected_type_args) {
355   return internal::InvalidArgumentTypeError(
356       argument_name, arg_index, actual_type,
357       internal::ToExpectedTypesSet(expected_type, expected_type_args...));
358 }
359 
360 base::Status MissingArgumentError(const char* argument_name);
361 
362 base::Status ToInvalidArgumentError(const char* argument_name,
363                                     size_t arg_index,
364                                     const base::Status& error);
365 
366 template <typename... args>
ExtractArgument(size_t argc,sqlite3_value ** argv,const char * argument_name,size_t arg_index,SqlValue::Type expected_type,args...expected_type_args)367 base::StatusOr<SqlValue> ExtractArgument(size_t argc,
368                                          sqlite3_value** argv,
369                                          const char* argument_name,
370                                          size_t arg_index,
371                                          SqlValue::Type expected_type,
372                                          args... expected_type_args) {
373   return internal::ExtractArgument(
374       argc, argv, argument_name, arg_index,
375       internal::ToExpectedTypesSet(expected_type, expected_type_args...));
376 }
377 
378 }  // namespace perfetto::trace_processor::sqlite::utils
379 
380 #endif  // SRC_TRACE_PROCESSOR_SQLITE_SQLITE_UTILS_H_
381