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