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 50 inline bool IsOpEq(int op) { 51 return op == SQLITE_INDEX_CONSTRAINT_EQ; 52 } 53 54 inline bool IsOpGe(int op) { 55 return op == SQLITE_INDEX_CONSTRAINT_GE; 56 } 57 58 inline bool IsOpGt(int op) { 59 return op == SQLITE_INDEX_CONSTRAINT_GT; 60 } 61 62 inline bool IsOpLe(int op) { 63 return op == SQLITE_INDEX_CONSTRAINT_LE; 64 } 65 66 inline bool IsOpLt(int op) { 67 return op == SQLITE_INDEX_CONSTRAINT_LT; 68 } 69 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 89 inline bool IsOpIsNull(int op) { 90 return op == SQLITE_INDEX_CONSTRAINT_ISNULL; 91 } 92 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 <> 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 <> 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 <> 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 <> 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 <> 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 <> 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: 150 NumericPredicate(int op, T constant) : op_(op), constant_(constant) {} 151 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> 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 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> 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> 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> 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> 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> 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> 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 <> 342 inline void ReportSqliteResult(sqlite3_context* ctx, int32_t value) { 343 sqlite3_result_int(ctx, value); 344 } 345 346 template <> 347 inline void ReportSqliteResult(sqlite3_context* ctx, int64_t value) { 348 sqlite3_result_int64(ctx, value); 349 } 350 351 template <> 352 inline void ReportSqliteResult(sqlite3_context* ctx, uint8_t value) { 353 sqlite3_result_int(ctx, value); 354 } 355 356 template <> 357 inline void ReportSqliteResult(sqlite3_context* ctx, uint32_t value) { 358 sqlite3_result_int64(ctx, value); 359 } 360 361 template <> 362 inline void ReportSqliteResult(sqlite3_context* ctx, double value) { 363 sqlite3_result_double(ctx, value); 364 } 365 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 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> 444 int CompareValuesAsc(const T& f, const T& s) { 445 return f < s ? -1 : (f > s ? 1 : 0); 446 } 447 448 template <typename T> 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