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