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 <math.h>
21 #include <sqlite3.h>
22
23 #include <functional>
24 #include <limits>
25 #include <string>
26
27 #include "perfetto/base/logging.h"
28 #include "perfetto/ext/base/optional.h"
29 #include "src/trace_processor/sqlite/scoped_db.h"
30 #include "src/trace_processor/sqlite/sqlite_table.h"
31
32 namespace perfetto {
33 namespace trace_processor {
34 namespace sqlite_utils {
35
36 const auto kSqliteStatic = reinterpret_cast<sqlite3_destructor_type>(0);
37 const auto kSqliteTransient = reinterpret_cast<sqlite3_destructor_type>(-1);
38
39 template <typename T>
40 using is_numeric =
41 typename std::enable_if<std::is_arithmetic<T>::value, T>::type;
42
43 template <typename T>
44 using is_float =
45 typename std::enable_if<std::is_floating_point<T>::value, T>::type;
46
47 template <typename T>
48 using is_int = typename std::enable_if<std::is_integral<T>::value, T>::type;
49
IsOpEq(int op)50 inline bool IsOpEq(int op) {
51 return op == SQLITE_INDEX_CONSTRAINT_EQ;
52 }
53
IsOpGe(int op)54 inline bool IsOpGe(int op) {
55 return op == SQLITE_INDEX_CONSTRAINT_GE;
56 }
57
IsOpGt(int op)58 inline bool IsOpGt(int op) {
59 return op == SQLITE_INDEX_CONSTRAINT_GT;
60 }
61
IsOpLe(int op)62 inline bool IsOpLe(int op) {
63 return op == SQLITE_INDEX_CONSTRAINT_LE;
64 }
65
IsOpLt(int op)66 inline bool IsOpLt(int op) {
67 return op == SQLITE_INDEX_CONSTRAINT_LT;
68 }
69
OpToString(int op)70 inline std::string OpToString(int op) {
71 switch (op) {
72 case SQLITE_INDEX_CONSTRAINT_EQ:
73 return "=";
74 case SQLITE_INDEX_CONSTRAINT_NE:
75 return "!=";
76 case SQLITE_INDEX_CONSTRAINT_GE:
77 return ">=";
78 case SQLITE_INDEX_CONSTRAINT_GT:
79 return ">";
80 case SQLITE_INDEX_CONSTRAINT_LE:
81 return "<=";
82 case SQLITE_INDEX_CONSTRAINT_LT:
83 return "<";
84 case SQLITE_INDEX_CONSTRAINT_LIKE:
85 return "like";
86 default:
87 PERFETTO_FATAL("Operator to string conversion not impemented for %d", op);
88 }
89 }
90
IsOpIsNull(int op)91 inline bool IsOpIsNull(int op) {
92 return op == SQLITE_INDEX_CONSTRAINT_ISNULL;
93 }
94
IsOpIsNotNull(int op)95 inline bool IsOpIsNotNull(int op) {
96 return op == SQLITE_INDEX_CONSTRAINT_ISNOTNULL;
97 }
98
99 template <typename T>
100 T ExtractSqliteValue(sqlite3_value* value);
101
102 template <>
ExtractSqliteValue(sqlite3_value * value)103 inline uint8_t ExtractSqliteValue(sqlite3_value* value) {
104 auto type = sqlite3_value_type(value);
105 PERFETTO_DCHECK(type == SQLITE_INTEGER);
106 return static_cast<uint8_t>(sqlite3_value_int(value));
107 }
108
109 template <>
ExtractSqliteValue(sqlite3_value * value)110 inline uint32_t ExtractSqliteValue(sqlite3_value* value) {
111 auto type = sqlite3_value_type(value);
112 PERFETTO_DCHECK(type == SQLITE_INTEGER);
113 return static_cast<uint32_t>(sqlite3_value_int64(value));
114 }
115
116 template <>
ExtractSqliteValue(sqlite3_value * value)117 inline int32_t ExtractSqliteValue(sqlite3_value* value) {
118 auto type = sqlite3_value_type(value);
119 PERFETTO_DCHECK(type == SQLITE_INTEGER);
120 return sqlite3_value_int(value);
121 }
122
123 template <>
ExtractSqliteValue(sqlite3_value * value)124 inline int64_t ExtractSqliteValue(sqlite3_value* value) {
125 auto type = sqlite3_value_type(value);
126 PERFETTO_DCHECK(type == SQLITE_INTEGER);
127 return static_cast<int64_t>(sqlite3_value_int64(value));
128 }
129
130 template <>
ExtractSqliteValue(sqlite3_value * value)131 inline double ExtractSqliteValue(sqlite3_value* value) {
132 auto type = sqlite3_value_type(value);
133 PERFETTO_DCHECK(type == SQLITE_FLOAT || type == SQLITE_INTEGER);
134 return sqlite3_value_double(value);
135 }
136
137 template <>
ExtractSqliteValue(sqlite3_value * value)138 inline bool ExtractSqliteValue(sqlite3_value* value) {
139 auto type = sqlite3_value_type(value);
140 PERFETTO_DCHECK(type == SQLITE_INTEGER);
141 return static_cast<bool>(sqlite3_value_int(value));
142 }
143
144 // Do not add a uint64_t version of ExtractSqliteValue. You should not be using
145 // uint64_t at all given that SQLite doesn't support it.
146
147 template <>
ExtractSqliteValue(sqlite3_value * value)148 inline const char* ExtractSqliteValue(sqlite3_value* value) {
149 auto type = sqlite3_value_type(value);
150 PERFETTO_DCHECK(type == SQLITE_TEXT);
151 return reinterpret_cast<const char*>(sqlite3_value_text(value));
152 }
153
154 template <>
ExtractSqliteValue(sqlite3_value * value)155 inline std::string ExtractSqliteValue(sqlite3_value* value) {
156 return ExtractSqliteValue<const char*>(value);
157 }
158
159 template <typename T>
160 class NumericPredicate {
161 public:
NumericPredicate(int op,T constant)162 NumericPredicate(int op, T constant) : op_(op), constant_(constant) {}
163
operator()164 PERFETTO_ALWAYS_INLINE bool operator()(T other) const {
165 switch (op_) {
166 case SQLITE_INDEX_CONSTRAINT_ISNULL:
167 return false;
168 case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
169 return true;
170 case SQLITE_INDEX_CONSTRAINT_EQ:
171 case SQLITE_INDEX_CONSTRAINT_IS:
172 return std::equal_to<T>()(other, constant_);
173 case SQLITE_INDEX_CONSTRAINT_NE:
174 case SQLITE_INDEX_CONSTRAINT_ISNOT:
175 return std::not_equal_to<T>()(other, constant_);
176 case SQLITE_INDEX_CONSTRAINT_GE:
177 return std::greater_equal<T>()(other, constant_);
178 case SQLITE_INDEX_CONSTRAINT_GT:
179 return std::greater<T>()(other, constant_);
180 case SQLITE_INDEX_CONSTRAINT_LE:
181 return std::less_equal<T>()(other, constant_);
182 case SQLITE_INDEX_CONSTRAINT_LT:
183 return std::less<T>()(other, constant_);
184 default:
185 PERFETTO_FATAL("For GCC");
186 }
187 }
188
189 private:
190 int op_;
191 T constant_;
192 };
193
194 template <typename T, typename sqlite_utils::is_numeric<T>* = nullptr>
CreateNumericPredicate(int op,sqlite3_value * value)195 NumericPredicate<T> CreateNumericPredicate(int op, sqlite3_value* value) {
196 T extracted =
197 IsOpIsNull(op) || IsOpIsNotNull(op) ? 0 : ExtractSqliteValue<T>(value);
198 return NumericPredicate<T>(op, extracted);
199 }
200
CreateStringPredicate(int op,sqlite3_value * value)201 inline std::function<bool(const char*)> CreateStringPredicate(
202 int op,
203 sqlite3_value* value) {
204 switch (op) {
205 case SQLITE_INDEX_CONSTRAINT_ISNULL:
206 return [](const char* f) { return f == nullptr; };
207 case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
208 return [](const char* f) { return f != nullptr; };
209 }
210
211 const char* val = reinterpret_cast<const char*>(sqlite3_value_text(value));
212
213 // If the value compared against is null, then to stay consistent with SQL
214 // handling, we have to return false for non-null operators.
215 if (val == nullptr) {
216 PERFETTO_CHECK(op != SQLITE_INDEX_CONSTRAINT_IS &&
217 op != SQLITE_INDEX_CONSTRAINT_ISNOT);
218 return [](const char*) { return false; };
219 }
220
221 switch (op) {
222 case SQLITE_INDEX_CONSTRAINT_EQ:
223 case SQLITE_INDEX_CONSTRAINT_IS:
224 return [val](const char* str) {
225 return str != nullptr && strcmp(str, val) == 0;
226 };
227 case SQLITE_INDEX_CONSTRAINT_NE:
228 case SQLITE_INDEX_CONSTRAINT_ISNOT:
229 return [val](const char* str) {
230 return str != nullptr && strcmp(str, val) != 0;
231 };
232 case SQLITE_INDEX_CONSTRAINT_GE:
233 return [val](const char* str) {
234 return str != nullptr && strcmp(str, val) >= 0;
235 };
236 case SQLITE_INDEX_CONSTRAINT_GT:
237 return [val](const char* str) {
238 return str != nullptr && strcmp(str, val) > 0;
239 };
240 case SQLITE_INDEX_CONSTRAINT_LE:
241 return [val](const char* str) {
242 return str != nullptr && strcmp(str, val) <= 0;
243 };
244 case SQLITE_INDEX_CONSTRAINT_LT:
245 return [val](const char* str) {
246 return str != nullptr && strcmp(str, val) < 0;
247 };
248 case SQLITE_INDEX_CONSTRAINT_LIKE:
249 return [val](const char* str) {
250 return str != nullptr && sqlite3_strlike(val, str, 0) == 0;
251 };
252 case SQLITE_INDEX_CONSTRAINT_GLOB:
253 return [val](const char* str) {
254 return str != nullptr && sqlite3_strglob(val, str) == 0;
255 };
256 default:
257 PERFETTO_FATAL("For GCC");
258 }
259 }
260
261 // Greater bound for floating point numbers.
262 template <typename T, typename sqlite_utils::is_float<T>* = nullptr>
FindGtBound(bool is_eq,sqlite3_value * sqlite_val)263 T FindGtBound(bool is_eq, sqlite3_value* sqlite_val) {
264 constexpr auto kMax = static_cast<long double>(std::numeric_limits<T>::max());
265 auto type = sqlite3_value_type(sqlite_val);
266 if (type != SQLITE_INTEGER && type != SQLITE_FLOAT) {
267 return kMax;
268 }
269
270 // If this is a strict gt bound then just get the next highest float
271 // after value.
272 auto value = ExtractSqliteValue<T>(sqlite_val);
273 return is_eq ? value : nexttoward(value, kMax);
274 }
275
276 template <typename T, typename sqlite_utils::is_int<T>* = nullptr>
FindGtBound(bool is_eq,sqlite3_value * sqlite_val)277 T FindGtBound(bool is_eq, sqlite3_value* sqlite_val) {
278 auto type = sqlite3_value_type(sqlite_val);
279 if (type == SQLITE_INTEGER) {
280 auto value = ExtractSqliteValue<T>(sqlite_val);
281 return is_eq ? value : value + 1;
282 } else if (type == SQLITE_FLOAT) {
283 auto value = ExtractSqliteValue<double>(sqlite_val);
284 auto above = ceil(value);
285 auto cast = static_cast<T>(above);
286 return value < above ? cast : (is_eq ? cast : cast + 1);
287 } else {
288 return std::numeric_limits<T>::max();
289 }
290 }
291
292 template <typename T, typename sqlite_utils::is_float<T>* = nullptr>
FindLtBound(bool is_eq,sqlite3_value * sqlite_val)293 T FindLtBound(bool is_eq, sqlite3_value* sqlite_val) {
294 constexpr auto kMin =
295 static_cast<long double>(std::numeric_limits<T>::lowest());
296 auto type = sqlite3_value_type(sqlite_val);
297 if (type != SQLITE_INTEGER && type != SQLITE_FLOAT) {
298 return kMin;
299 }
300
301 // If this is a strict lt bound then just get the next lowest float
302 // before value.
303 auto value = ExtractSqliteValue<T>(sqlite_val);
304 return is_eq ? value : nexttoward(value, kMin);
305 }
306
307 template <typename T, typename sqlite_utils::is_int<T>* = nullptr>
FindLtBound(bool is_eq,sqlite3_value * sqlite_val)308 T FindLtBound(bool is_eq, sqlite3_value* sqlite_val) {
309 auto type = sqlite3_value_type(sqlite_val);
310 if (type == SQLITE_INTEGER) {
311 auto value = ExtractSqliteValue<T>(sqlite_val);
312 return is_eq ? value : value - 1;
313 } else if (type == SQLITE_FLOAT) {
314 auto value = ExtractSqliteValue<double>(sqlite_val);
315 auto below = floor(value);
316 auto cast = static_cast<T>(below);
317 return value > below ? cast : (is_eq ? cast : cast - 1);
318 } else {
319 return std::numeric_limits<T>::max();
320 }
321 }
322
323 template <typename T, typename sqlite_utils::is_float<T>* = nullptr>
FindEqBound(sqlite3_value * sqlite_val)324 T FindEqBound(sqlite3_value* sqlite_val) {
325 auto type = sqlite3_value_type(sqlite_val);
326 if (type != SQLITE_INTEGER && type != SQLITE_FLOAT) {
327 return std::numeric_limits<T>::max();
328 }
329 return ExtractSqliteValue<T>(sqlite_val);
330 }
331
332 template <typename T, typename sqlite_utils::is_int<T>* = nullptr>
FindEqBound(sqlite3_value * sqlite_val)333 T FindEqBound(sqlite3_value* sqlite_val) {
334 auto type = sqlite3_value_type(sqlite_val);
335 if (type == SQLITE_INTEGER) {
336 return ExtractSqliteValue<T>(sqlite_val);
337 } else if (type == SQLITE_FLOAT) {
338 auto value = ExtractSqliteValue<double>(sqlite_val);
339 auto below = floor(value);
340 auto cast = static_cast<T>(below);
341 return value > below ? std::numeric_limits<T>::max() : cast;
342 } else {
343 return std::numeric_limits<T>::max();
344 }
345 }
346
347 template <typename T>
348 void ReportSqliteResult(sqlite3_context*, T value);
349
350 // Do not add a uint64_t version of ReportSqliteResult. You should not be using
351 // uint64_t at all given that SQLite doesn't support it.
352
353 template <>
ReportSqliteResult(sqlite3_context * ctx,int32_t value)354 inline void ReportSqliteResult(sqlite3_context* ctx, int32_t value) {
355 sqlite3_result_int(ctx, value);
356 }
357
358 template <>
ReportSqliteResult(sqlite3_context * ctx,int64_t value)359 inline void ReportSqliteResult(sqlite3_context* ctx, int64_t value) {
360 sqlite3_result_int64(ctx, value);
361 }
362
363 template <>
ReportSqliteResult(sqlite3_context * ctx,uint8_t value)364 inline void ReportSqliteResult(sqlite3_context* ctx, uint8_t value) {
365 sqlite3_result_int(ctx, value);
366 }
367
368 template <>
ReportSqliteResult(sqlite3_context * ctx,uint32_t value)369 inline void ReportSqliteResult(sqlite3_context* ctx, uint32_t value) {
370 sqlite3_result_int64(ctx, value);
371 }
372
373 template <>
ReportSqliteResult(sqlite3_context * ctx,bool value)374 inline void ReportSqliteResult(sqlite3_context* ctx, bool value) {
375 sqlite3_result_int(ctx, value);
376 }
377
378 template <>
ReportSqliteResult(sqlite3_context * ctx,double value)379 inline void ReportSqliteResult(sqlite3_context* ctx, double value) {
380 sqlite3_result_double(ctx, value);
381 }
382
SqliteValueAsString(sqlite3_value * value)383 inline std::string SqliteValueAsString(sqlite3_value* value) {
384 switch (sqlite3_value_type(value)) {
385 case SQLITE_INTEGER:
386 return std::to_string(sqlite3_value_int64(value));
387 case SQLITE_FLOAT:
388 return std::to_string(sqlite3_value_double(value));
389 case SQLITE_TEXT: {
390 const char* str =
391 reinterpret_cast<const char*>(sqlite3_value_text(value));
392 return "'" + std::string(str) + "'";
393 }
394 default:
395 PERFETTO_FATAL("Unknown value type %d", sqlite3_value_type(value));
396 }
397 }
398
GetColumnsForTable(sqlite3 * db,const std::string & raw_table_name)399 inline std::vector<SqliteTable::Column> GetColumnsForTable(
400 sqlite3* db,
401 const std::string& raw_table_name) {
402 char sql[1024];
403 const char kRawSql[] = "SELECT name, type from pragma_table_info(\"%s\")";
404
405 // Support names which are table valued functions with arguments.
406 std::string table_name = raw_table_name.substr(0, raw_table_name.find('('));
407 int n = snprintf(sql, sizeof(sql), kRawSql, table_name.c_str());
408 PERFETTO_DCHECK(n >= 0 || static_cast<size_t>(n) < sizeof(sql));
409
410 sqlite3_stmt* raw_stmt = nullptr;
411 int err = sqlite3_prepare_v2(db, sql, n, &raw_stmt, nullptr);
412 if (err != SQLITE_OK) {
413 PERFETTO_ELOG("Preparing database failed");
414 return {};
415 }
416 ScopedStmt stmt(raw_stmt);
417 PERFETTO_DCHECK(sqlite3_column_count(*stmt) == 2);
418
419 std::vector<SqliteTable::Column> columns;
420 for (;;) {
421 err = sqlite3_step(raw_stmt);
422 if (err == SQLITE_DONE)
423 break;
424 if (err != SQLITE_ROW) {
425 PERFETTO_ELOG("Querying schema of table %s failed",
426 raw_table_name.c_str());
427 return {};
428 }
429
430 const char* name =
431 reinterpret_cast<const char*>(sqlite3_column_text(*stmt, 0));
432 const char* raw_type =
433 reinterpret_cast<const char*>(sqlite3_column_text(*stmt, 1));
434 if (!name || !raw_type || !*name) {
435 PERFETTO_FATAL("Schema for %s has invalid column values",
436 raw_table_name.c_str());
437 }
438
439 SqlValue::Type type;
440 if (strcmp(raw_type, "STRING") == 0) {
441 type = SqlValue::Type::kString;
442 } else if (strcmp(raw_type, "DOUBLE") == 0) {
443 type = SqlValue::Type::kDouble;
444 } else if (strcmp(raw_type, "BIG INT") == 0 ||
445 strcmp(raw_type, "UNSIGNED INT") == 0 ||
446 strcmp(raw_type, "INT") == 0 ||
447 strcmp(raw_type, "BOOLEAN") == 0) {
448 type = SqlValue::Type::kLong;
449 } else if (!*raw_type) {
450 PERFETTO_DLOG("Unknown column type for %s %s", raw_table_name.c_str(),
451 name);
452 type = SqlValue::Type::kNull;
453 } else {
454 PERFETTO_FATAL("Unknown column type '%s' on table %s", raw_type,
455 raw_table_name.c_str());
456 }
457 columns.emplace_back(columns.size(), name, type);
458 }
459 return columns;
460 }
461
462 template <typename T>
CompareValuesAsc(const T & f,const T & s)463 int CompareValuesAsc(const T& f, const T& s) {
464 return f < s ? -1 : (f > s ? 1 : 0);
465 }
466
467 template <typename T>
CompareValuesDesc(const T & f,const T & s)468 int CompareValuesDesc(const T& f, const T& s) {
469 return -CompareValuesAsc(f, s);
470 }
471
472 } // namespace sqlite_utils
473 } // namespace trace_processor
474 } // namespace perfetto
475
476 #endif // SRC_TRACE_PROCESSOR_SQLITE_SQLITE_UTILS_H_
477