• 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 #include <bitset>
23 #include <cstddef>
24 #include <cstring>
25 #include <optional>
26 #include <utility>
27 
28 #include "perfetto/base/logging.h"
29 #include "perfetto/base/status.h"
30 #include "perfetto/ext/base/status_or.h"
31 #include "perfetto/ext/base/string_utils.h"
32 #include "perfetto/ext/base/string_view.h"
33 #include "perfetto/trace_processor/basic_types.h"
34 #include "src/trace_processor/sqlite/scoped_db.h"
35 #include "src/trace_processor/sqlite/sqlite_table.h"
36 
37 namespace perfetto {
38 namespace trace_processor {
39 namespace sqlite_utils {
40 
41 const auto kSqliteStatic = reinterpret_cast<sqlite3_destructor_type>(0);
42 const auto kSqliteTransient = reinterpret_cast<sqlite3_destructor_type>(-1);
43 
IsOpEq(int op)44 inline bool IsOpEq(int op) {
45   return op == SQLITE_INDEX_CONSTRAINT_EQ;
46 }
IsOpLe(int op)47 inline bool IsOpLe(int op) {
48   return op == SQLITE_INDEX_CONSTRAINT_LE;
49 }
IsOpLt(int op)50 inline bool IsOpLt(int op) {
51   return op == SQLITE_INDEX_CONSTRAINT_LT;
52 }
IsOpGe(int op)53 inline bool IsOpGe(int op) {
54   return op == SQLITE_INDEX_CONSTRAINT_GE;
55 }
IsOpGt(int op)56 inline bool IsOpGt(int op) {
57   return op == SQLITE_INDEX_CONSTRAINT_GT;
58 }
59 
SqliteTypeToSqlValueType(int sqlite_type)60 inline SqlValue::Type SqliteTypeToSqlValueType(int sqlite_type) {
61   switch (sqlite_type) {
62     case SQLITE_NULL:
63       return SqlValue::Type::kNull;
64     case SQLITE_BLOB:
65       return SqlValue::Type::kBytes;
66     case SQLITE_INTEGER:
67       return SqlValue::Type::kLong;
68     case SQLITE_FLOAT:
69       return SqlValue::Type::kDouble;
70     case SQLITE_TEXT:
71       return SqlValue::Type::kString;
72   }
73   PERFETTO_FATAL("Unknown SQLite type %d", sqlite_type);
74 }
75 
SqliteValueToSqlValue(sqlite3_value * value)76 inline SqlValue SqliteValueToSqlValue(sqlite3_value* value) {
77   SqlValue sql_value;
78   switch (sqlite3_value_type(value)) {
79     case SQLITE_INTEGER:
80       sql_value.type = SqlValue::Type::kLong;
81       sql_value.long_value = sqlite3_value_int64(value);
82       break;
83     case SQLITE_FLOAT:
84       sql_value.type = SqlValue::Type::kDouble;
85       sql_value.double_value = sqlite3_value_double(value);
86       break;
87     case SQLITE_TEXT:
88       sql_value.type = SqlValue::Type::kString;
89       sql_value.string_value =
90           reinterpret_cast<const char*>(sqlite3_value_text(value));
91       break;
92     case SQLITE_BLOB:
93       sql_value.type = SqlValue::Type::kBytes;
94       sql_value.bytes_value = sqlite3_value_blob(value);
95       sql_value.bytes_count = static_cast<size_t>(sqlite3_value_bytes(value));
96       break;
97   }
98   return sql_value;
99 }
100 
SqlValueToString(SqlValue value)101 inline std::optional<std::string> SqlValueToString(SqlValue value) {
102   switch (value.type) {
103     case SqlValue::Type::kString:
104       return value.AsString();
105     case SqlValue::Type::kDouble:
106       return std::to_string(value.AsDouble());
107     case SqlValue::Type::kLong:
108       return std::to_string(value.AsLong());
109     case SqlValue::Type::kBytes:
110     case SqlValue::Type::kNull:
111       return std::nullopt;
112   }
113   PERFETTO_FATAL("For GCC");
114 }
115 
116 inline void ReportSqlValue(
117     sqlite3_context* ctx,
118     const SqlValue& value,
119     sqlite3_destructor_type string_destructor = kSqliteTransient,
120     sqlite3_destructor_type bytes_destructor = kSqliteTransient) {
121   switch (value.type) {
122     case SqlValue::Type::kLong:
123       sqlite3_result_int64(ctx, value.long_value);
124       break;
125     case SqlValue::Type::kDouble:
126       sqlite3_result_double(ctx, value.double_value);
127       break;
128     case SqlValue::Type::kString: {
129       sqlite3_result_text(ctx, value.string_value, -1, string_destructor);
130       break;
131     }
132     case SqlValue::Type::kBytes:
133       sqlite3_result_blob(ctx, value.bytes_value,
134                           static_cast<int>(value.bytes_count),
135                           bytes_destructor);
136       break;
137     case SqlValue::Type::kNull:
138       sqlite3_result_null(ctx);
139       break;
140   }
141 }
142 
ExpandedSqlForStmt(sqlite3_stmt * stmt)143 inline ScopedSqliteString ExpandedSqlForStmt(sqlite3_stmt* stmt) {
144   return ScopedSqliteString(sqlite3_expanded_sql(stmt));
145 }
146 
FormatErrorMessage(base::StringView sql,sqlite3 * db,int error_code)147 inline base::Status FormatErrorMessage(base::StringView sql,
148                                        sqlite3* db,
149                                        int error_code) {
150   uint32_t offset = static_cast<uint32_t>(sqlite3_error_offset(db));
151 
152   auto error_opt = FindLineWithOffset(sql, offset);
153 
154   if (!error_opt.has_value()) {
155     return base::ErrStatus("Error: %s (errcode: %d)", sqlite3_errmsg(db),
156                            error_code);
157   }
158 
159   auto error = error_opt.value();
160 
161   return base::ErrStatus(
162       "Error in line:%u, col: %u.\n"
163       "%s\n"
164       "%s^\n"
165       "%s (errcode: %d)",
166       error.line_num, error.line_offset + 1, error.line.ToStdString().c_str(),
167       std::string(error.line_offset, ' ').c_str(), sqlite3_errmsg(db),
168       error_code);
169 }
170 
FormatErrorMessage(sqlite3_stmt * stmt,std::optional<base::StringView> sql,sqlite3 * db,int error_code)171 inline base::Status FormatErrorMessage(sqlite3_stmt* stmt,
172                                        std::optional<base::StringView> sql,
173                                        sqlite3* db,
174                                        int error_code) {
175   if (stmt) {
176     auto expanded_sql = ExpandedSqlForStmt(stmt);
177     PERFETTO_CHECK(expanded_sql);
178     return FormatErrorMessage(expanded_sql.get(), db, error_code);
179   }
180   PERFETTO_CHECK(sql.has_value());
181   return FormatErrorMessage(sql.value(), db, error_code);
182 }
183 
PrepareStmt(sqlite3 * db,const char * sql,ScopedStmt * stmt,const char ** tail)184 inline base::Status PrepareStmt(sqlite3* db,
185                                 const char* sql,
186                                 ScopedStmt* stmt,
187                                 const char** tail) {
188   sqlite3_stmt* raw_stmt = nullptr;
189   int err = sqlite3_prepare_v2(db, sql, -1, &raw_stmt, tail);
190   stmt->reset(raw_stmt);
191   if (err != SQLITE_OK)
192     return base::ErrStatus("%s", FormatErrorMessage(sql, db, err).c_message());
193   return base::OkStatus();
194 }
195 
IsStmtDone(sqlite3_stmt * stmt)196 inline bool IsStmtDone(sqlite3_stmt* stmt) {
197   return !sqlite3_stmt_busy(stmt);
198 }
199 
StepStmtUntilDone(sqlite3_stmt * stmt)200 inline base::Status StepStmtUntilDone(sqlite3_stmt* stmt) {
201   PERFETTO_DCHECK(stmt);
202 
203   if (IsStmtDone(stmt))
204     return base::OkStatus();
205 
206   int err;
207   for (err = sqlite3_step(stmt); err == SQLITE_ROW; err = sqlite3_step(stmt)) {
208   }
209   if (err != SQLITE_DONE) {
210     auto db = sqlite3_db_handle(stmt);
211     return base::ErrStatus(
212         "%s", FormatErrorMessage(stmt, std::nullopt, db, err).c_message());
213   }
214   return base::OkStatus();
215 }
216 
SetSqliteError(sqlite3_context * ctx,const base::Status & status)217 inline void SetSqliteError(sqlite3_context* ctx, const base::Status& status) {
218   PERFETTO_CHECK(!status.ok());
219   sqlite3_result_error(ctx, status.c_message(), -1);
220 }
221 
SetSqliteError(sqlite3_context * ctx,const std::string & function_name,const base::Status & status)222 inline void SetSqliteError(sqlite3_context* ctx,
223                            const std::string& function_name,
224                            const base::Status& status) {
225   SetSqliteError(ctx, base::ErrStatus("%s: %s", function_name.c_str(),
226                                       status.c_message()));
227 }
228 
229 // Exracts the given type from the SqlValue if |value| can fit
230 // in the provided optional. Note that SqlValue::kNull will always
231 // succeed and cause std::nullopt to be set.
232 //
233 // Returns base::ErrStatus if the type does not match or does not
234 // fit in the width of the provided optional type (i.e. int64 value
235 // not fitting in int32 optional).
236 base::Status ExtractFromSqlValue(const SqlValue& value,
237                                  std::optional<int64_t>&);
238 base::Status ExtractFromSqlValue(const SqlValue& value,
239                                  std::optional<int32_t>&);
240 base::Status ExtractFromSqlValue(const SqlValue& value,
241                                  std::optional<uint32_t>&);
242 base::Status ExtractFromSqlValue(const SqlValue& value, std::optional<double>&);
243 base::Status ExtractFromSqlValue(const SqlValue& value,
244                                  std::optional<const char*>&);
245 
246 // Returns the column names for the table named by |raw_table_name|.
247 base::Status GetColumnsForTable(sqlite3* db,
248                                 const std::string& raw_table_name,
249                                 std::vector<SqliteTable::Column>& columns);
250 
251 // Reads a `SQLITE_TEXT` value and returns it as a wstring (UTF-16) in the
252 // default byte order. `value` must be a `SQLITE_TEXT`.
253 std::wstring SqliteValueToWString(sqlite3_value* value);
254 
255 // Given an SqlValue::Type, converts it to a human-readable string.
256 // This should really only be used for debugging messages.
257 const char* SqliteTypeToFriendlyString(SqlValue::Type type);
258 
259 // Verifies if |value| has the type represented by |expected_type|.
260 // Returns base::OkStatus if it does or an base::ErrStatus with an
261 // appropriate error mesage (incorporating |expected_type_str| if specified).
262 base::Status TypeCheckSqliteValue(sqlite3_value* value,
263                                   SqlValue::Type expected_type);
264 base::Status TypeCheckSqliteValue(sqlite3_value* value,
265                                   SqlValue::Type expected_type,
266                                   const char* expected_type_str);
267 
268 namespace internal {
269 
270 static_assert(sizeof(size_t) * 8 > SqlValue::kLastType);
271 using ExpectedTypesSet = std::bitset<SqlValue::kLastType + 1>;
272 
273 template <typename... args>
ToExpectedTypesSet(args...expected_type_args)274 constexpr ExpectedTypesSet ToExpectedTypesSet(args... expected_type_args) {
275   ExpectedTypesSet set;
276   for (const SqlValue::Type t : {expected_type_args...}) {
277     set.set(static_cast<size_t>(t));
278   }
279   return set;
280 }
281 
282 base::StatusOr<SqlValue> ExtractArgument(size_t argc,
283                                          sqlite3_value** argv,
284                                          const char* argument_name,
285                                          size_t arg_index,
286                                          ExpectedTypesSet expected_types);
287 base::Status InvalidArgumentTypeError(const char* argument_name,
288                                       size_t arg_index,
289                                       SqlValue::Type actual_type,
290                                       ExpectedTypesSet expected_types);
291 }  // namespace internal
292 
293 template <typename... args>
InvalidArgumentTypeError(const char * argument_name,size_t arg_index,SqlValue::Type actual_type,SqlValue::Type expected_type,args...expected_type_args)294 base::Status InvalidArgumentTypeError(const char* argument_name,
295                                       size_t arg_index,
296                                       SqlValue::Type actual_type,
297                                       SqlValue::Type expected_type,
298                                       args... expected_type_args) {
299   return internal::InvalidArgumentTypeError(
300       argument_name, arg_index, actual_type,
301       internal::ToExpectedTypesSet(expected_type, expected_type_args...));
302 }
303 
304 base::Status MissingArgumentError(const char* argument_name);
305 
306 base::Status ToInvalidArgumentError(const char* argument_name,
307                                     size_t arg_index,
308                                     const base::Status error);
309 
310 template <typename... args>
ExtractArgument(size_t argc,sqlite3_value ** argv,const char * argument_name,size_t arg_index,SqlValue::Type expected_type,args...expected_type_args)311 base::StatusOr<SqlValue> ExtractArgument(size_t argc,
312                                          sqlite3_value** argv,
313                                          const char* argument_name,
314                                          size_t arg_index,
315                                          SqlValue::Type expected_type,
316                                          args... expected_type_args) {
317   return internal::ExtractArgument(
318       argc, argv, argument_name, arg_index,
319       internal::ToExpectedTypesSet(expected_type, expected_type_args...));
320 }
321 
322 }  // namespace sqlite_utils
323 }  // namespace trace_processor
324 }  // namespace perfetto
325 
326 #endif  // SRC_TRACE_PROCESSOR_SQLITE_SQLITE_UTILS_H_
327