• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     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_vtab * tab,base::Status s)162 inline int SetError(sqlite3_vtab* tab, base::Status s) {
163   return SetError(tab, s.c_message());
164 }
165 
SetError(sqlite3_context * ctx,const base::Status & status)166 inline void SetError(sqlite3_context* ctx, const base::Status& status) {
167   PERFETTO_CHECK(!status.ok());
168   sqlite::result::Error(ctx, status.c_message());
169 }
170 
SetError(sqlite3_context * ctx,const std::string & function_name,const base::Status & status)171 inline void SetError(sqlite3_context* ctx,
172                      const std::string& function_name,
173                      const base::Status& status) {
174   SetError(ctx, base::ErrStatus("%s: %s", function_name.c_str(),
175                                 status.c_message()));
176 }
177 
178 // For a given |sqlite3_index_info| struct received in a BestIndex call, returns
179 // whether all |arg_count| arguments (with |is_arg_column| indicating whether a
180 // given column is a function argument) have exactly one equality constraint
181 // associated with them.
182 //
183 // If so, the associated constraint is omitted and the argvIndex is mapped to
184 // the corresponding argument's index.
ValidateFunctionArguments(sqlite3_index_info * info,size_t arg_count,const std::function<bool (size_t)> & is_arg_column)185 inline base::Status ValidateFunctionArguments(
186     sqlite3_index_info* info,
187     size_t arg_count,
188     const std::function<bool(size_t)>& is_arg_column) {
189   std::vector<bool> present;
190   size_t present_count = 0;
191   for (int i = 0; i < info->nConstraint; ++i) {
192     const auto& in = info->aConstraint[i];
193     if (!in.usable) {
194       continue;
195     }
196     auto cs_col = static_cast<size_t>(in.iColumn);
197     if (!is_arg_column(cs_col)) {
198       continue;
199     }
200     if (!IsOpEq(in.op)) {
201       return base::ErrStatus(
202           "Unexpected non equality constraints for column %zu", cs_col);
203     }
204     if (cs_col >= present.size()) {
205       present.resize(cs_col + 1);
206     }
207     if (present[cs_col]) {
208       return base::ErrStatus("Unexpected multiple constraints for column %zu",
209                              cs_col);
210     }
211     present[cs_col] = true;
212     present_count++;
213 
214     auto& out = info->aConstraintUsage[i];
215     out.argvIndex = static_cast<int>(present_count);
216     out.omit = true;
217   }
218   if (present_count != arg_count) {
219     return base::ErrStatus(
220         "Unexpected missing argument: expected %zu, actual %zu", arg_count,
221         present_count);
222   }
223   return base::OkStatus();
224 }
225 
226 // Converts the given SqlValue type to the type string SQLite understands.
SqlValueTypeToString(SqlValue::Type type)227 inline std::string SqlValueTypeToString(SqlValue::Type type) {
228   switch (type) {
229     case SqlValue::Type::kString:
230       return "TEXT";
231     case SqlValue::Type::kLong:
232       return "BIGINT";
233     case SqlValue::Type::kDouble:
234       return "DOUBLE";
235     case SqlValue::Type::kBytes:
236       return "BLOB";
237     case SqlValue::Type::kNull:
238       PERFETTO_FATAL("Cannot map unknown column type");
239   }
240   PERFETTO_FATAL("Not reached");  // For gcc
241 }
242 
243 // Exracts the given type from the SqlValue if |value| can fit
244 // in the provided optional. Note that SqlValue::kNull will always
245 // succeed and cause std::nullopt to be set.
246 //
247 // Returns base::ErrStatus if the type does not match or does not
248 // fit in the width of the provided optional type (i.e. int64 value
249 // not fitting in int32 optional).
250 base::Status ExtractFromSqlValue(const SqlValue& value,
251                                  std::optional<int64_t>&);
252 base::Status ExtractFromSqlValue(const SqlValue& value,
253                                  std::optional<int32_t>&);
254 base::Status ExtractFromSqlValue(const SqlValue& value,
255                                  std::optional<uint32_t>&);
256 base::Status ExtractFromSqlValue(const SqlValue& value, std::optional<double>&);
257 base::Status ExtractFromSqlValue(const SqlValue& value,
258                                  std::optional<const char*>&);
259 
260 // Returns the column names for the table named by |raw_table_name|.
261 base::Status GetColumnsForTable(
262     sqlite3* db,
263     const std::string& raw_table_name,
264     std::vector<std::pair<SqlValue::Type, std::string>>& columns);
265 
266 // Reads a `SQLITE_TEXT` value and returns it as a wstring (UTF-16) in the
267 // default byte order. `value` must be a `SQLITE_TEXT`.
268 std::wstring SqliteValueToWString(sqlite3_value* value);
269 
270 // Given an SqlValue::Type, converts it to a human-readable string.
271 // This should really only be used for debugging messages.
272 const char* SqliteTypeToFriendlyString(SqlValue::Type type);
273 
274 // Verifies if |argc| matches |expected_argc| and returns an appropriate error
275 // message if they don't match.
276 base::Status CheckArgCount(const char* function_name,
277                            size_t argc,
278                            size_t expected_argc);
279 
280 // Type-safe helpers to extract an arg value from a sqlite3_value*, returning an
281 // appropriate message if it fails.
282 base::StatusOr<int64_t> ExtractIntArg(const char* function_name,
283                                       const char* arg_name,
284                                       sqlite3_value* value);
285 base::StatusOr<double> ExtractDoubleArg(const char* function_name,
286                                         const char* arg_name,
287                                         sqlite3_value* value);
288 base::StatusOr<std::string> ExtractStringArg(const char* function_name,
289                                              const char* arg_name,
290                                              sqlite3_value* value);
291 
292 // Verifies if |value| has the type represented by |expected_type|.
293 // Returns base::OkStatus if it does or an base::ErrStatus with an
294 // appropriate error mesage (incorporating |expected_type_str| if specified).
295 base::Status TypeCheckSqliteValue(sqlite3_value* value,
296                                   SqlValue::Type expected_type);
297 base::Status TypeCheckSqliteValue(sqlite3_value* value,
298                                   SqlValue::Type expected_type,
299                                   const char* expected_type_str);
300 
301 namespace internal {
302 
303 static_assert(sizeof(size_t) * 8 > SqlValue::kLastType);
304 using ExpectedTypesSet = std::bitset<SqlValue::kLastType + 1>;
305 
306 template <typename... args>
ToExpectedTypesSet(args...expected_type_args)307 constexpr ExpectedTypesSet ToExpectedTypesSet(args... expected_type_args) {
308   ExpectedTypesSet set;
309   for (const SqlValue::Type t : {expected_type_args...}) {
310     set.set(static_cast<size_t>(t));
311   }
312   return set;
313 }
314 
315 base::StatusOr<SqlValue> ExtractArgument(size_t argc,
316                                          sqlite3_value** argv,
317                                          const char* argument_name,
318                                          size_t arg_index,
319                                          ExpectedTypesSet expected_types);
320 base::Status InvalidArgumentTypeError(const char* argument_name,
321                                       size_t arg_index,
322                                       SqlValue::Type actual_type,
323                                       ExpectedTypesSet expected_types);
324 }  // namespace internal
325 
326 template <typename... args>
InvalidArgumentTypeError(const char * argument_name,size_t arg_index,SqlValue::Type actual_type,SqlValue::Type expected_type,args...expected_type_args)327 base::Status InvalidArgumentTypeError(const char* argument_name,
328                                       size_t arg_index,
329                                       SqlValue::Type actual_type,
330                                       SqlValue::Type expected_type,
331                                       args... expected_type_args) {
332   return internal::InvalidArgumentTypeError(
333       argument_name, arg_index, actual_type,
334       internal::ToExpectedTypesSet(expected_type, expected_type_args...));
335 }
336 
337 base::Status MissingArgumentError(const char* argument_name);
338 
339 base::Status ToInvalidArgumentError(const char* argument_name,
340                                     size_t arg_index,
341                                     const base::Status& error);
342 
343 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)344 base::StatusOr<SqlValue> ExtractArgument(size_t argc,
345                                          sqlite3_value** argv,
346                                          const char* argument_name,
347                                          size_t arg_index,
348                                          SqlValue::Type expected_type,
349                                          args... expected_type_args) {
350   return internal::ExtractArgument(
351       argc, argv, argument_name, arg_index,
352       internal::ToExpectedTypesSet(expected_type, expected_type_args...));
353 }
354 
355 }  // namespace perfetto::trace_processor::sqlite::utils
356 
357 #endif  // SRC_TRACE_PROCESSOR_SQLITE_SQLITE_UTILS_H_
358