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