• 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 <math.h>
21 #include <sqlite3.h>
22 
23 #include "perfetto/ext/base/string_utils.h"
24 #include "perfetto/trace_processor/basic_types.h"
25 #include "src/trace_processor/sqlite/scoped_db.h"
26 #include "src/trace_processor/sqlite/sqlite_table.h"
27 
28 namespace perfetto {
29 namespace trace_processor {
30 namespace sqlite_utils {
31 
32 const auto kSqliteStatic = reinterpret_cast<sqlite3_destructor_type>(0);
33 const auto kSqliteTransient = reinterpret_cast<sqlite3_destructor_type>(-1);
34 
IsOpEq(int op)35 inline bool IsOpEq(int op) {
36   return op == SQLITE_INDEX_CONSTRAINT_EQ;
37 }
IsOpLe(int op)38 inline bool IsOpLe(int op) {
39   return op == SQLITE_INDEX_CONSTRAINT_LE;
40 }
IsOpLt(int op)41 inline bool IsOpLt(int op) {
42   return op == SQLITE_INDEX_CONSTRAINT_LT;
43 }
IsOpGe(int op)44 inline bool IsOpGe(int op) {
45   return op == SQLITE_INDEX_CONSTRAINT_GE;
46 }
IsOpGt(int op)47 inline bool IsOpGt(int op) {
48   return op == SQLITE_INDEX_CONSTRAINT_GT;
49 }
50 
SqliteTypeToSqlValueType(int sqlite_type)51 inline SqlValue::Type SqliteTypeToSqlValueType(int sqlite_type) {
52   switch (sqlite_type) {
53     case SQLITE_NULL:
54       return SqlValue::Type::kNull;
55     case SQLITE_BLOB:
56       return SqlValue::Type::kBytes;
57     case SQLITE_INTEGER:
58       return SqlValue::Type::kLong;
59     case SQLITE_FLOAT:
60       return SqlValue::Type::kDouble;
61     case SQLITE_TEXT:
62       return SqlValue::Type::kString;
63   }
64   PERFETTO_FATAL("Unknown SQLite type %d", sqlite_type);
65 }
66 
SqliteValueToSqlValue(sqlite3_value * value)67 inline SqlValue SqliteValueToSqlValue(sqlite3_value* value) {
68   SqlValue sql_value;
69   switch (sqlite3_value_type(value)) {
70     case SQLITE_INTEGER:
71       sql_value.type = SqlValue::Type::kLong;
72       sql_value.long_value = sqlite3_value_int64(value);
73       break;
74     case SQLITE_FLOAT:
75       sql_value.type = SqlValue::Type::kDouble;
76       sql_value.double_value = sqlite3_value_double(value);
77       break;
78     case SQLITE_TEXT:
79       sql_value.type = SqlValue::Type::kString;
80       sql_value.string_value =
81           reinterpret_cast<const char*>(sqlite3_value_text(value));
82       break;
83     case SQLITE_BLOB:
84       sql_value.type = SqlValue::Type::kBytes;
85       sql_value.bytes_value = sqlite3_value_blob(value);
86       sql_value.bytes_count = static_cast<size_t>(sqlite3_value_bytes(value));
87       break;
88   }
89   return sql_value;
90 }
91 
SqlValueToString(SqlValue value)92 inline base::Optional<std::string> SqlValueToString(SqlValue value) {
93   switch (value.type) {
94     case SqlValue::Type::kString:
95       return value.AsString();
96     case SqlValue::Type::kDouble:
97       return std::to_string(value.AsDouble());
98     case SqlValue::Type::kLong:
99       return std::to_string(value.AsLong());
100     case SqlValue::Type::kBytes:
101     case SqlValue::Type::kNull:
102       return base::nullopt;
103   }
104   PERFETTO_FATAL("For GCC");
105 }
106 
107 inline void ReportSqlValue(
108     sqlite3_context* ctx,
109     const SqlValue& value,
110     sqlite3_destructor_type string_destructor = kSqliteTransient,
111     sqlite3_destructor_type bytes_destructor = kSqliteTransient) {
112   switch (value.type) {
113     case SqlValue::Type::kLong:
114       sqlite3_result_int64(ctx, value.long_value);
115       break;
116     case SqlValue::Type::kDouble:
117       sqlite3_result_double(ctx, value.double_value);
118       break;
119     case SqlValue::Type::kString: {
120       sqlite3_result_text(ctx, value.string_value, -1, string_destructor);
121       break;
122     }
123     case SqlValue::Type::kBytes:
124       sqlite3_result_blob(ctx, value.bytes_value,
125                           static_cast<int>(value.bytes_count),
126                           bytes_destructor);
127       break;
128     case SqlValue::Type::kNull:
129       sqlite3_result_null(ctx);
130       break;
131   }
132 }
133 
PrepareStmt(sqlite3 * db,const char * sql,ScopedStmt * stmt,const char ** tail)134 inline base::Status PrepareStmt(sqlite3* db,
135                                 const char* sql,
136                                 ScopedStmt* stmt,
137                                 const char** tail) {
138   sqlite3_stmt* raw_stmt = nullptr;
139   int err = sqlite3_prepare_v2(db, sql, -1, &raw_stmt, tail);
140   stmt->reset(raw_stmt);
141   if (err != SQLITE_OK)
142     return base::ErrStatus("%s (errcode: %d)", sqlite3_errmsg(db), err);
143   return base::OkStatus();
144 }
145 
IsStmtDone(sqlite3_stmt * stmt)146 inline bool IsStmtDone(sqlite3_stmt* stmt) {
147   return !sqlite3_stmt_busy(stmt);
148 }
149 
StepStmtUntilDone(sqlite3_stmt * stmt)150 inline base::Status StepStmtUntilDone(sqlite3_stmt* stmt) {
151   PERFETTO_DCHECK(stmt);
152 
153   if (IsStmtDone(stmt))
154     return base::OkStatus();
155 
156   int err;
157   for (err = sqlite3_step(stmt); err == SQLITE_ROW; err = sqlite3_step(stmt)) {
158   }
159   if (err != SQLITE_DONE) {
160     return base::ErrStatus("%s (errcode: %d)",
161                            sqlite3_errmsg(sqlite3_db_handle(stmt)), err);
162   }
163   return base::OkStatus();
164 }
165 
GetColumnsForTable(sqlite3 * db,const std::string & raw_table_name,std::vector<SqliteTable::Column> & columns)166 inline util::Status GetColumnsForTable(
167     sqlite3* db,
168     const std::string& raw_table_name,
169     std::vector<SqliteTable::Column>& columns) {
170   PERFETTO_DCHECK(columns.empty());
171   char sql[1024];
172   const char kRawSql[] = "SELECT name, type from pragma_table_info(\"%s\")";
173 
174   // Support names which are table valued functions with arguments.
175   std::string table_name = raw_table_name.substr(0, raw_table_name.find('('));
176   size_t n = base::SprintfTrunc(sql, sizeof(sql), kRawSql, table_name.c_str());
177   PERFETTO_DCHECK(n > 0);
178 
179   sqlite3_stmt* raw_stmt = nullptr;
180   int err =
181       sqlite3_prepare_v2(db, sql, static_cast<int>(n), &raw_stmt, nullptr);
182   if (err != SQLITE_OK) {
183     return util::ErrStatus("Preparing database failed");
184   }
185   ScopedStmt stmt(raw_stmt);
186   PERFETTO_DCHECK(sqlite3_column_count(*stmt) == 2);
187 
188   for (;;) {
189     err = sqlite3_step(raw_stmt);
190     if (err == SQLITE_DONE)
191       break;
192     if (err != SQLITE_ROW) {
193       return util::ErrStatus("Querying schema of table %s failed",
194                              raw_table_name.c_str());
195     }
196 
197     const char* name =
198         reinterpret_cast<const char*>(sqlite3_column_text(*stmt, 0));
199     const char* raw_type =
200         reinterpret_cast<const char*>(sqlite3_column_text(*stmt, 1));
201     if (!name || !raw_type || !*name) {
202       return util::ErrStatus("Schema for %s has invalid column values",
203                              raw_table_name.c_str());
204     }
205 
206     SqlValue::Type type;
207     if (base::CaseInsensitiveEqual(raw_type, "STRING") ||
208         base::CaseInsensitiveEqual(raw_type, "TEXT")) {
209       type = SqlValue::Type::kString;
210     } else if (base::CaseInsensitiveEqual(raw_type, "DOUBLE")) {
211       type = SqlValue::Type::kDouble;
212     } else if (base::CaseInsensitiveEqual(raw_type, "BIG INT") ||
213                base::CaseInsensitiveEqual(raw_type, "UNSIGNED INT") ||
214                base::CaseInsensitiveEqual(raw_type, "INT") ||
215                base::CaseInsensitiveEqual(raw_type, "BOOLEAN") ||
216                base::CaseInsensitiveEqual(raw_type, "INTEGER")) {
217       type = SqlValue::Type::kLong;
218     } else if (!*raw_type) {
219       PERFETTO_DLOG("Unknown column type for %s %s", raw_table_name.c_str(),
220                     name);
221       type = SqlValue::Type::kNull;
222     } else {
223       return util::ErrStatus("Unknown column type '%s' on table %s", raw_type,
224                              raw_table_name.c_str());
225     }
226     columns.emplace_back(columns.size(), name, type);
227   }
228   return util::OkStatus();
229 }
230 
231 }  // namespace sqlite_utils
232 }  // namespace trace_processor
233 }  // namespace perfetto
234 
235 #endif  // SRC_TRACE_PROCESSOR_SQLITE_SQLITE_UTILS_H_
236