• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 #include "src/trace_processor/sqlite/db_sqlite_table.h"
18 
19 #include <sqlite3.h>
20 #include <algorithm>
21 #include <cmath>
22 #include <cstddef>
23 #include <cstdint>
24 #include <iterator>
25 #include <memory>
26 #include <numeric>
27 #include <optional>
28 #include <string>
29 #include <utility>
30 #include <vector>
31 
32 #include "perfetto/base/compiler.h"
33 #include "perfetto/base/logging.h"
34 #include "perfetto/base/status.h"
35 #include "perfetto/ext/base/small_vector.h"
36 #include "perfetto/ext/base/status_or.h"
37 #include "perfetto/ext/base/string_splitter.h"
38 #include "perfetto/ext/base/string_utils.h"
39 #include "perfetto/ext/base/string_view.h"
40 #include "perfetto/public/compiler.h"
41 #include "perfetto/trace_processor/basic_types.h"
42 #include "src/trace_processor/containers/row_map.h"
43 #include "src/trace_processor/db/column/types.h"
44 #include "src/trace_processor/db/runtime_table.h"
45 #include "src/trace_processor/db/table.h"
46 #include "src/trace_processor/perfetto_sql/intrinsics/table_functions/static_table_function.h"
47 #include "src/trace_processor/sqlite/module_lifecycle_manager.h"
48 #include "src/trace_processor/sqlite/sqlite_utils.h"
49 #include "src/trace_processor/tp_metatrace.h"
50 #include "src/trace_processor/util/regex.h"
51 
52 #include "protos/perfetto/trace_processor/metatrace_categories.pbzero.h"
53 
54 namespace perfetto::trace_processor {
55 namespace {
56 
SqliteOpToFilterOp(int sqlite_op)57 std::optional<FilterOp> SqliteOpToFilterOp(int sqlite_op) {
58   switch (sqlite_op) {
59     case SQLITE_INDEX_CONSTRAINT_EQ:
60       return FilterOp::kEq;
61     case SQLITE_INDEX_CONSTRAINT_GT:
62       return FilterOp::kGt;
63     case SQLITE_INDEX_CONSTRAINT_LT:
64       return FilterOp::kLt;
65     case SQLITE_INDEX_CONSTRAINT_NE:
66       return FilterOp::kNe;
67     case SQLITE_INDEX_CONSTRAINT_GE:
68       return FilterOp::kGe;
69     case SQLITE_INDEX_CONSTRAINT_LE:
70       return FilterOp::kLe;
71     case SQLITE_INDEX_CONSTRAINT_ISNULL:
72       return FilterOp::kIsNull;
73     case SQLITE_INDEX_CONSTRAINT_ISNOTNULL:
74       return FilterOp::kIsNotNull;
75     case SQLITE_INDEX_CONSTRAINT_GLOB:
76       return FilterOp::kGlob;
77     case SQLITE_INDEX_CONSTRAINT_REGEXP:
78       if constexpr (regex::IsRegexSupported()) {
79         return FilterOp::kRegex;
80       }
81       return std::nullopt;
82     case SQLITE_INDEX_CONSTRAINT_LIKE:
83     // TODO(lalitm): start supporting these constraints.
84     case SQLITE_INDEX_CONSTRAINT_LIMIT:
85     case SQLITE_INDEX_CONSTRAINT_OFFSET:
86     case SQLITE_INDEX_CONSTRAINT_IS:
87     case SQLITE_INDEX_CONSTRAINT_ISNOT:
88       return std::nullopt;
89     default:
90       PERFETTO_FATAL("Currently unsupported constraint");
91   }
92 }
93 
94 class SafeStringWriter {
95  public:
AppendString(const char * s)96   void AppendString(const char* s) {
97     for (const char* c = s; *c; ++c) {
98       buffer_.emplace_back(*c);
99     }
100   }
101 
AppendString(const std::string & s)102   void AppendString(const std::string& s) {
103     for (char c : s) {
104       buffer_.emplace_back(c);
105     }
106   }
107 
GetStringView() const108   base::StringView GetStringView() const {
109     return {buffer_.data(), buffer_.size()};
110   }
111 
112  private:
113   base::SmallVector<char, 2048> buffer_;
114 };
115 
CreateTableStatementFromSchema(const Table::Schema & schema,const char * table_name)116 std::string CreateTableStatementFromSchema(const Table::Schema& schema,
117                                            const char* table_name) {
118   std::string stmt = "CREATE TABLE x(";
119   for (const auto& col : schema.columns) {
120     std::string c =
121         col.name + " " + sqlite::utils::SqlValueTypeToSqliteTypeName(col.type);
122     if (col.is_hidden) {
123       c += " HIDDEN";
124     }
125     stmt += c + ",";
126   }
127 
128   auto it =
129       std::find_if(schema.columns.begin(), schema.columns.end(),
130                    [](const Table::Schema::Column& c) { return c.is_id; });
131   if (it == schema.columns.end()) {
132     PERFETTO_FATAL(
133         "id column not found in %s. All tables need to contain an id column;",
134         table_name);
135   }
136   stmt += "PRIMARY KEY(" + it->name + ")";
137   stmt += ") WITHOUT ROWID;";
138   return stmt;
139 }
140 
SqliteValueToSqlValueChecked(SqlValue * sql_val,sqlite3_value * value,const Constraint & cs,sqlite3_vtab * vtab)141 int SqliteValueToSqlValueChecked(SqlValue* sql_val,
142                                  sqlite3_value* value,
143                                  const Constraint& cs,
144                                  sqlite3_vtab* vtab) {
145   *sql_val = sqlite::utils::SqliteValueToSqlValue(value);
146   if constexpr (regex::IsRegexSupported()) {
147     if (cs.op == FilterOp::kRegex) {
148       if (cs.value.type != SqlValue::kString) {
149         return sqlite::utils::SetError(vtab, "Value has to be a string");
150       }
151       if (auto st = regex::Regex::Create(cs.value.AsString()); !st.ok()) {
152         return sqlite::utils::SetError(vtab, st.status().c_message());
153       }
154     }
155   }
156   return SQLITE_OK;
157 }
158 
ReadLetterAndInt(char letter,base::StringSplitter * splitter)159 inline uint32_t ReadLetterAndInt(char letter, base::StringSplitter* splitter) {
160   PERFETTO_CHECK(splitter->Next());
161   PERFETTO_DCHECK(splitter->cur_token_size() >= 2);
162   PERFETTO_DCHECK(splitter->cur_token()[0] == letter);
163   return *base::CStringToUInt32(splitter->cur_token() + 1);
164 }
165 
ReadLetterAndLong(char letter,base::StringSplitter * splitter)166 inline uint64_t ReadLetterAndLong(char letter, base::StringSplitter* splitter) {
167   PERFETTO_CHECK(splitter->Next());
168   PERFETTO_DCHECK(splitter->cur_token_size() >= 2);
169   PERFETTO_DCHECK(splitter->cur_token()[0] == letter);
170   return *base::CStringToUInt64(splitter->cur_token() + 1);
171 }
172 
ReadIdxStrAndUpdateCursor(DbSqliteModule::Cursor * cursor,const char * idx_str,sqlite3_value ** argv)173 int ReadIdxStrAndUpdateCursor(DbSqliteModule::Cursor* cursor,
174                               const char* idx_str,
175                               sqlite3_value** argv) {
176   base::StringSplitter splitter(idx_str, ',');
177 
178   uint32_t cs_count = ReadLetterAndInt('C', &splitter);
179 
180   Query q;
181   q.constraints.resize(cs_count);
182 
183   uint32_t c_offset = 0;
184   for (auto& cs : q.constraints) {
185     PERFETTO_CHECK(splitter.Next());
186     cs.col_idx = *base::CStringToUInt32(splitter.cur_token());
187     PERFETTO_CHECK(splitter.Next());
188     cs.op = static_cast<FilterOp>(*base::CStringToUInt32(splitter.cur_token()));
189 
190     if (int ret = SqliteValueToSqlValueChecked(&cs.value, argv[c_offset++], cs,
191                                                cursor->pVtab);
192         ret != SQLITE_OK) {
193       return ret;
194     }
195   }
196 
197   uint32_t ob_count = ReadLetterAndInt('O', &splitter);
198 
199   q.orders.resize(ob_count);
200   for (auto& ob : q.orders) {
201     PERFETTO_CHECK(splitter.Next());
202     ob.col_idx = *base::CStringToUInt32(splitter.cur_token());
203     PERFETTO_CHECK(splitter.Next());
204     ob.desc = *base::CStringToUInt32(splitter.cur_token());
205   }
206 
207   // DISTINCT
208   q.order_type =
209       static_cast<Query::OrderType>(ReadLetterAndInt('D', &splitter));
210 
211   // Cols used
212   q.cols_used = ReadLetterAndLong('U', &splitter);
213 
214   // LIMIT
215   if (ReadLetterAndInt('L', &splitter)) {
216     auto val_op = sqlite::utils::SqliteValueToSqlValue(argv[c_offset++]);
217     if (val_op.type != SqlValue::kLong) {
218       return sqlite::utils::SetError(cursor->pVtab,
219                                      "LIMIT value has to be an INT");
220     }
221     q.limit = val_op.AsLong();
222   }
223 
224   // OFFSET
225   if (ReadLetterAndInt('F', &splitter)) {
226     auto val_op = sqlite::utils::SqliteValueToSqlValue(argv[c_offset++]);
227     if (val_op.type != SqlValue::kLong) {
228       return sqlite::utils::SetError(cursor->pVtab,
229                                      "OFFSET value has to be an INT");
230     }
231     q.offset = static_cast<uint32_t>(val_op.AsLong());
232   }
233 
234   cursor->query = std::move(q);
235   return SQLITE_OK;
236 }
237 
TryCacheCreateSortedTable(DbSqliteModule::Cursor * cursor,const Table::Schema & schema,bool is_same_idx)238 PERFETTO_ALWAYS_INLINE void TryCacheCreateSortedTable(
239     DbSqliteModule::Cursor* cursor,
240     const Table::Schema& schema,
241     bool is_same_idx) {
242   if (!is_same_idx) {
243     cursor->repeated_cache_count = 0;
244     return;
245   }
246 
247   // Only try and create the cached table on exactly the third time we see
248   // this constraint set.
249   constexpr uint32_t kRepeatedThreshold = 3;
250   if (cursor->sorted_cache_table ||
251       cursor->repeated_cache_count++ != kRepeatedThreshold) {
252     return;
253   }
254 
255   // If we have more than one constraint, we can't cache the table using
256   // this method.
257   if (cursor->query.constraints.size() != 1) {
258     return;
259   }
260 
261   // If the constraing is not an equality constraint, there's little
262   // benefit to caching
263   const auto& c = cursor->query.constraints.front();
264   if (c.op != FilterOp::kEq) {
265     return;
266   }
267 
268   // If the column is already sorted, we don't need to cache at all.
269   if (schema.columns[c.col_idx].is_sorted) {
270     return;
271   }
272 
273   // Try again to get the result or start caching it.
274   cursor->sorted_cache_table =
275       cursor->upstream_table->Sort({Order{c.col_idx, false}});
276 }
277 
FilterAndSortMetatrace(const std::string & table_name,const Table::Schema & schema,DbSqliteModule::Cursor * cursor,metatrace::Record * r)278 void FilterAndSortMetatrace(const std::string& table_name,
279                             const Table::Schema& schema,
280                             DbSqliteModule::Cursor* cursor,
281                             metatrace::Record* r) {
282   r->AddArg("Table", table_name);
283   for (const Constraint& c : cursor->query.constraints) {
284     SafeStringWriter writer;
285     writer.AppendString(schema.columns[c.col_idx].name);
286 
287     writer.AppendString(" ");
288     switch (c.op) {
289       case FilterOp::kEq:
290         writer.AppendString("=");
291         break;
292       case FilterOp::kGe:
293         writer.AppendString(">=");
294         break;
295       case FilterOp::kGt:
296         writer.AppendString(">");
297         break;
298       case FilterOp::kLe:
299         writer.AppendString("<=");
300         break;
301       case FilterOp::kLt:
302         writer.AppendString("<");
303         break;
304       case FilterOp::kNe:
305         writer.AppendString("!=");
306         break;
307       case FilterOp::kIsNull:
308         writer.AppendString("IS");
309         break;
310       case FilterOp::kIsNotNull:
311         writer.AppendString("IS NOT");
312         break;
313       case FilterOp::kGlob:
314         writer.AppendString("GLOB");
315         break;
316       case FilterOp::kRegex:
317         writer.AppendString("REGEXP");
318         break;
319     }
320     writer.AppendString(" ");
321 
322     switch (c.value.type) {
323       case SqlValue::kString:
324         writer.AppendString(c.value.AsString());
325         break;
326       case SqlValue::kBytes:
327         writer.AppendString("<bytes>");
328         break;
329       case SqlValue::kNull:
330         writer.AppendString("<null>");
331         break;
332       case SqlValue::kDouble: {
333         writer.AppendString(std::to_string(c.value.AsDouble()));
334         break;
335       }
336       case SqlValue::kLong: {
337         writer.AppendString(std::to_string(c.value.AsLong()));
338         break;
339       }
340     }
341     r->AddArg("Constraint", writer.GetStringView());
342   }
343 
344   for (const auto& o : cursor->query.orders) {
345     SafeStringWriter writer;
346     writer.AppendString(schema.columns[o.col_idx].name);
347     if (o.desc)
348       writer.AppendString(" desc");
349     r->AddArg("Order by", writer.GetStringView());
350   }
351 }
352 
353 }  // namespace
354 
Create(sqlite3 * db,void * ctx,int argc,const char * const * argv,sqlite3_vtab ** vtab,char **)355 int DbSqliteModule::Create(sqlite3* db,
356                            void* ctx,
357                            int argc,
358                            const char* const* argv,
359                            sqlite3_vtab** vtab,
360                            char**) {
361   PERFETTO_CHECK(argc == 3);
362   auto* context = GetContext(ctx);
363   auto state = std::move(context->temporary_create_state);
364   PERFETTO_CHECK(state);
365 
366   std::string sql = CreateTableStatementFromSchema(state->schema, argv[2]);
367   if (int ret = sqlite3_declare_vtab(db, sql.c_str()); ret != SQLITE_OK) {
368     return ret;
369   }
370   std::unique_ptr<Vtab> res = std::make_unique<Vtab>();
371   res->state = context->manager.OnCreate(argv, std::move(state));
372   res->table_name = argv[2];
373   *vtab = res.release();
374   return SQLITE_OK;
375 }
376 
Destroy(sqlite3_vtab * vtab)377 int DbSqliteModule::Destroy(sqlite3_vtab* vtab) {
378   auto* t = GetVtab(vtab);
379   auto* s = sqlite::ModuleStateManager<DbSqliteModule>::GetState(t->state);
380   if (s->computation == TableComputation::kStatic) {
381     // SQLite does not read error messages returned from xDestroy so just pick
382     // the closest appropriate error code.
383     return SQLITE_READONLY;
384   }
385   std::unique_ptr<Vtab> tab(GetVtab(vtab));
386   sqlite::ModuleStateManager<DbSqliteModule>::OnDestroy(tab->state);
387   return SQLITE_OK;
388 }
389 
Connect(sqlite3 * db,void * ctx,int argc,const char * const * argv,sqlite3_vtab ** vtab,char **)390 int DbSqliteModule::Connect(sqlite3* db,
391                             void* ctx,
392                             int argc,
393                             const char* const* argv,
394                             sqlite3_vtab** vtab,
395                             char**) {
396   PERFETTO_CHECK(argc == 3);
397   auto* context = GetContext(ctx);
398 
399   std::unique_ptr<Vtab> res = std::make_unique<Vtab>();
400   res->state = context->manager.OnConnect(argv);
401   res->table_name = argv[2];
402 
403   auto* state =
404       sqlite::ModuleStateManager<DbSqliteModule>::GetState(res->state);
405   std::string sql = CreateTableStatementFromSchema(state->schema, argv[2]);
406   if (int ret = sqlite3_declare_vtab(db, sql.c_str()); ret != SQLITE_OK) {
407     // If the registration happens to fail, make sure to disconnect the state
408     // again.
409     sqlite::ModuleStateManager<DbSqliteModule>::OnDisconnect(res->state);
410     return ret;
411   }
412   *vtab = res.release();
413   return SQLITE_OK;
414 }
415 
Disconnect(sqlite3_vtab * vtab)416 int DbSqliteModule::Disconnect(sqlite3_vtab* vtab) {
417   std::unique_ptr<Vtab> tab(GetVtab(vtab));
418   sqlite::ModuleStateManager<DbSqliteModule>::OnDisconnect(tab->state);
419   return SQLITE_OK;
420 }
421 
BestIndex(sqlite3_vtab * vtab,sqlite3_index_info * info)422 int DbSqliteModule::BestIndex(sqlite3_vtab* vtab, sqlite3_index_info* info) {
423   auto* t = GetVtab(vtab);
424   auto* s = sqlite::ModuleStateManager<DbSqliteModule>::GetState(t->state);
425 
426   const Table* table = nullptr;
427   switch (s->computation) {
428     case TableComputation::kStatic:
429       table = s->static_table;
430       break;
431     case TableComputation::kRuntime:
432       table = s->runtime_table.get();
433       break;
434     case TableComputation::kTableFunction:
435       break;
436   }
437 
438   uint32_t row_count;
439   int argv_index;
440   switch (s->computation) {
441     case TableComputation::kStatic:
442     case TableComputation::kRuntime:
443       row_count = table->row_count();
444       argv_index = 1;
445       break;
446     case TableComputation::kTableFunction:
447       base::Status status = sqlite::utils::ValidateFunctionArguments(
448           info, static_cast<size_t>(s->argument_count),
449           [s](uint32_t i) { return s->schema.columns[i].is_hidden; });
450       if (!status.ok()) {
451         // TODO(lalitm): instead of returning SQLITE_CONSTRAINT which shows the
452         // user a very cryptic error message, consider instead SQLITE_OK but
453         // with a very high (~infinite) cost. If SQLite still chose the query
454         // plan after that, we can throw a proper error message in xFilter.
455         return SQLITE_CONSTRAINT;
456       }
457       row_count = s->static_table_function->EstimateRowCount();
458       argv_index = 1 + s->argument_count;
459       break;
460   }
461 
462   std::vector<int> cs_idxes;
463 
464   // Limit and offset are a nonstandard type of constraint. We can check if they
465   // are present in the query here, but we won't save them as standard
466   // constraints and only add them to `idx_str` later.
467   int limit = -1;
468   int offset = -1;
469   bool has_unknown_constraint = false;
470 
471   cs_idxes.reserve(static_cast<uint32_t>(info->nConstraint));
472   for (int i = 0; i < info->nConstraint; ++i) {
473     const auto& c = info->aConstraint[i];
474     if (!c.usable || info->aConstraintUsage[i].omit) {
475       continue;
476     }
477     if (std::optional<FilterOp> opt_op = SqliteOpToFilterOp(c.op); !opt_op) {
478       if (c.op == SQLITE_INDEX_CONSTRAINT_LIMIT) {
479         limit = i;
480       } else if (c.op == SQLITE_INDEX_CONSTRAINT_OFFSET) {
481         offset = i;
482       } else {
483         has_unknown_constraint = true;
484       }
485       continue;
486     }
487     cs_idxes.push_back(i);
488   }
489 
490   std::vector<int> ob_idxes(static_cast<uint32_t>(info->nOrderBy));
491   std::iota(ob_idxes.begin(), ob_idxes.end(), 0);
492 
493   // Reorder constraints to consider the constraints on columns which are
494   // cheaper to filter first.
495   {
496     std::sort(
497         cs_idxes.begin(), cs_idxes.end(), [s, info, &table](int a, int b) {
498           auto a_idx = static_cast<uint32_t>(info->aConstraint[a].iColumn);
499           auto b_idx = static_cast<uint32_t>(info->aConstraint[b].iColumn);
500           const auto& a_col = s->schema.columns[a_idx];
501           const auto& b_col = s->schema.columns[b_idx];
502 
503           // Id columns are the most efficient to filter, as they don't have a
504           // support in real data.
505           if (a_col.is_id || b_col.is_id)
506             return a_col.is_id && !b_col.is_id;
507 
508           // Set id columns are inherently sorted and have fast filtering
509           // operations.
510           if (a_col.is_set_id || b_col.is_set_id)
511             return a_col.is_set_id && !b_col.is_set_id;
512 
513           // Intrinsically sorted column is more efficient to sort than
514           // extrinsically sorted column.
515           if (a_col.is_sorted || b_col.is_sorted)
516             return a_col.is_sorted && !b_col.is_sorted;
517 
518           // Extrinsically sorted column is more efficient to sort than unsorted
519           // column.
520           if (table) {
521             auto a_has_idx = table->GetIndex({a_idx});
522             auto b_has_idx = table->GetIndex({b_idx});
523             if (a_has_idx || b_has_idx)
524               return a_has_idx && !b_has_idx;
525           }
526 
527           bool a_is_eq = sqlite::utils::IsOpEq(info->aConstraint[a].op);
528           bool b_is_eq = sqlite::utils::IsOpEq(info->aConstraint[a].op);
529           if (a_is_eq || b_is_eq) {
530             return a_is_eq && !b_is_eq;
531           }
532 
533           // TODO(lalitm): introduce more orderings here based on empirical
534           // data.
535           return false;
536         });
537   }
538 
539   // Remove any order by constraints which also have an equality constraint.
540   {
541     auto p = [info, &cs_idxes](int o_idx) {
542       auto& o = info->aOrderBy[o_idx];
543       auto inner_p = [info, &o](int c_idx) {
544         auto& c = info->aConstraint[c_idx];
545         return c.iColumn == o.iColumn && sqlite::utils::IsOpEq(c.op);
546       };
547       return std::any_of(cs_idxes.begin(), cs_idxes.end(), inner_p);
548     };
549     ob_idxes.erase(std::remove_if(ob_idxes.begin(), ob_idxes.end(), p),
550                    ob_idxes.end());
551   }
552 
553   // Go through the order by constraints in reverse order and eliminate
554   // constraints until the first non-sorted column or the first order by in
555   // descending order.
556   {
557     auto p = [info, s](int o_idx) {
558       auto& o = info->aOrderBy[o_idx];
559       const auto& col = s->schema.columns[static_cast<uint32_t>(o.iColumn)];
560       return o.desc || !col.is_sorted;
561     };
562     auto first_non_sorted_it =
563         std::find_if(ob_idxes.rbegin(), ob_idxes.rend(), p);
564     auto pop_count = std::distance(ob_idxes.rbegin(), first_non_sorted_it);
565     ob_idxes.resize(ob_idxes.size() - static_cast<uint32_t>(pop_count));
566   }
567 
568   // Create index string. It contains information query Trace Processor will
569   // have to run. It can be split into 6 segments: C (constraints), O (orders),
570   // D (distinct), U (used), L (limit) and F (offset). It can be directly mapped
571   // into `Query` type. The number after C and O signifies how many
572   // constraints/orders there are. The number after D maps to the
573   // Query::Distinct enum value.
574   //
575   // "C2,0,0,2,1,O1,0,1,D1,U5,L0,F1" maps to:
576   // - "C2,0,0,2,1" - two constraints: kEq on first column and kNe on third
577   //   column.
578   // - "O1,0,1" - one order by: descending on first column.
579   // - "D1" - kUnsorted distinct.
580   // - "U5" - Columns 0 and 2 used.
581   // - "L1" - LIMIT set. "L0" if no limit.
582   // - "F1" - OFFSET set. Can only be set if "L1".
583 
584   // Constraints:
585   std::string idx_str = "C";
586   idx_str += std::to_string(cs_idxes.size());
587   for (int i : cs_idxes) {
588     const auto& c = info->aConstraint[i];
589     auto& o = info->aConstraintUsage[i];
590     o.omit = true;
591     o.argvIndex = argv_index++;
592 
593     auto op = SqliteOpToFilterOp(c.op);
594     PERFETTO_DCHECK(op);
595 
596     idx_str += ',';
597     idx_str += std::to_string(c.iColumn);
598     idx_str += ',';
599     idx_str += std::to_string(static_cast<uint32_t>(*op));
600   }
601   idx_str += ",";
602 
603   // Orders:
604   idx_str += "O";
605   idx_str += std::to_string(ob_idxes.size());
606   for (int i : ob_idxes) {
607     idx_str += ',';
608     idx_str += std::to_string(info->aOrderBy[i].iColumn);
609     idx_str += ',';
610     idx_str += std::to_string(info->aOrderBy[i].desc);
611   }
612   idx_str += ",";
613 
614   // Distinct:
615   idx_str += "D";
616   if (ob_idxes.size() == 1 && PERFETTO_POPCOUNT(info->colUsed) == 1) {
617     switch (sqlite3_vtab_distinct(info)) {
618       case 0:
619       case 1:
620         idx_str += std::to_string(static_cast<int>(Query::OrderType::kSort));
621         break;
622       case 2:
623         idx_str +=
624             std::to_string(static_cast<int>(Query::OrderType::kDistinct));
625         break;
626       case 3:
627         idx_str += std::to_string(
628             static_cast<int>(Query::OrderType::kDistinctAndSort));
629         break;
630       default:
631         PERFETTO_FATAL("Invalid sqlite3_vtab_distinct result");
632     }
633   } else {
634     // TODO(mayzner): Remove this if condition after implementing multicolumn
635     // distinct.
636     idx_str += std::to_string(static_cast<int>(Query::OrderType::kSort));
637   }
638   idx_str += ",";
639 
640   // Columns used.
641   idx_str += "U";
642   idx_str += std::to_string(info->colUsed);
643   idx_str += ",";
644 
645   // LIMIT. Save as "L1" if limit is present and "L0" if not.
646   idx_str += "L";
647   if (limit == -1 || has_unknown_constraint) {
648     idx_str += "0";
649   } else {
650     auto& o = info->aConstraintUsage[limit];
651     o.omit = true;
652     o.argvIndex = argv_index++;
653     idx_str += "1";
654   }
655   idx_str += ",";
656 
657   // OFFSET. Save as "F1" if offset is present and "F0" if not.
658   idx_str += "F";
659   if (offset == -1 || has_unknown_constraint) {
660     idx_str += "0";
661   } else {
662     auto& o = info->aConstraintUsage[offset];
663     o.omit = true;
664     o.argvIndex = argv_index++;
665     idx_str += "1";
666   }
667 
668   info->idxStr = sqlite3_mprintf("%s", idx_str.c_str());
669 
670   info->idxNum = t->best_index_num++;
671   info->needToFreeIdxStr = true;
672 
673   // We can sort on any column correctly.
674   info->orderByConsumed = true;
675 
676   auto cost_and_rows =
677       EstimateCost(s->schema, row_count, info, cs_idxes, ob_idxes);
678   info->estimatedCost = cost_and_rows.cost;
679   info->estimatedRows = cost_and_rows.rows;
680 
681   PERFETTO_TP_TRACE(
682       metatrace::Category::QUERY_TIMELINE, "DB_SQLITE_BEST_INDEX",
683       [&](metatrace::Record* record) {
684         record->AddArg("name", t->table_name.c_str());
685         record->AddArg("idxStr", info->idxStr);
686         record->AddArg("idxNum",
687                        base::StackString<32>("%d", info->idxNum).c_str());
688         record->AddArg(
689             "estimatedCost",
690             base::StackString<32>("%f", info->estimatedCost).c_str());
691         record->AddArg(
692             "estimatedRows",
693             base::StackString<32>("%lld", info->estimatedRows).c_str());
694       });
695 
696   return SQLITE_OK;
697 }
698 
Open(sqlite3_vtab * tab,sqlite3_vtab_cursor ** cursor)699 int DbSqliteModule::Open(sqlite3_vtab* tab, sqlite3_vtab_cursor** cursor) {
700   auto* t = GetVtab(tab);
701   auto* s = sqlite::ModuleStateManager<DbSqliteModule>::GetState(t->state);
702   std::unique_ptr<Cursor> c = std::make_unique<Cursor>();
703   switch (s->computation) {
704     case TableComputation::kStatic:
705       c->upstream_table = s->static_table;
706       break;
707     case TableComputation::kRuntime:
708       c->upstream_table = s->runtime_table.get();
709       break;
710     case TableComputation::kTableFunction:
711       c->table_function_arguments.resize(
712           static_cast<size_t>(s->argument_count));
713       break;
714   }
715   *cursor = c.release();
716   return SQLITE_OK;
717 }
718 
Close(sqlite3_vtab_cursor * cursor)719 int DbSqliteModule::Close(sqlite3_vtab_cursor* cursor) {
720   std::unique_ptr<Cursor> c(GetCursor(cursor));
721   return SQLITE_OK;
722 }
723 
Filter(sqlite3_vtab_cursor * cursor,int idx_num,const char * idx_str,int,sqlite3_value ** argv)724 int DbSqliteModule::Filter(sqlite3_vtab_cursor* cursor,
725                            int idx_num,
726                            const char* idx_str,
727                            int,
728                            sqlite3_value** argv) {
729   auto* c = GetCursor(cursor);
730   auto* t = GetVtab(cursor->pVtab);
731   auto* s = sqlite::ModuleStateManager<DbSqliteModule>::GetState(t->state);
732 
733   // Clear out the iterator before filtering to ensure the destructor is run
734   // before the table's destructor.
735   c->iterator = std::nullopt;
736 
737   size_t offset = c->table_function_arguments.size();
738   bool is_same_idx = idx_num == c->last_idx_num;
739   if (PERFETTO_LIKELY(is_same_idx)) {
740     for (auto& cs : c->query.constraints) {
741       if (int ret = SqliteValueToSqlValueChecked(&cs.value, argv[offset++], cs,
742                                                  c->pVtab);
743           ret != SQLITE_OK) {
744         return ret;
745       }
746     }
747   } else {
748     if (int r = ReadIdxStrAndUpdateCursor(c, idx_str, argv + offset);
749         r != SQLITE_OK) {
750       return r;
751     }
752     c->last_idx_num = idx_num;
753   }
754 
755   // Setup the upstream table based on the computation state.
756   switch (s->computation) {
757     case TableComputation::kStatic:
758     case TableComputation::kRuntime:
759       // Tries to create a sorted cached table which can be used to speed up
760       // filters below.
761       TryCacheCreateSortedTable(c, s->schema, is_same_idx);
762       break;
763     case TableComputation::kTableFunction: {
764       PERFETTO_TP_TRACE(
765           metatrace::Category::QUERY_DETAILED, "TABLE_FUNCTION_CALL",
766           [t](metatrace::Record* r) { r->AddArg("Name", t->table_name); });
767       for (uint32_t i = 0; i < c->table_function_arguments.size(); ++i) {
768         c->table_function_arguments[i] =
769             sqlite::utils::SqliteValueToSqlValue(argv[i]);
770       }
771       base::StatusOr<std::unique_ptr<Table>> table =
772           s->static_table_function->ComputeTable(c->table_function_arguments);
773       if (!table.ok()) {
774         base::StackString<1024> err("%s: %s", t->table_name.c_str(),
775                                     table.status().c_message());
776         return sqlite::utils::SetError(t, err.c_str());
777       }
778       c->dynamic_table = std::move(*table);
779       c->upstream_table = c->dynamic_table.get();
780       break;
781     }
782   }
783 
784   PERFETTO_TP_TRACE(metatrace::Category::QUERY_DETAILED,
785                     "DB_TABLE_FILTER_AND_SORT",
786                     [s, t, c](metatrace::Record* r) {
787                       FilterAndSortMetatrace(t->table_name, s->schema, c, r);
788                     });
789 
790   const auto* source_table =
791       c->sorted_cache_table ? &*c->sorted_cache_table : c->upstream_table;
792   RowMap filter_map = source_table->QueryToRowMap(c->query);
793   if (filter_map.IsRange() && filter_map.size() <= 1) {
794     // Currently, our criteria where we have a special fast path is if it's
795     // a single ranged row. We have this fast path for joins on id columns
796     // where we get repeated queries filtering down to a single row. The
797     // other path performs allocations when creating the new table as well
798     // as the iterator on the new table whereas this path only uses a single
799     // number and lives entirely on the stack.
800 
801     // TODO(lalitm): investigate some other criteria where it is beneficial
802     // to have a fast path and expand to them.
803     c->mode = Cursor::Mode::kSingleRow;
804     c->single_row = filter_map.size() == 1
805                         ? std::make_optional(filter_map.Get(0))
806                         : std::nullopt;
807     c->eof = !c->single_row.has_value();
808   } else {
809     c->mode = Cursor::Mode::kTable;
810     c->iterator = source_table->ApplyAndIterateRows(std::move(filter_map));
811     c->eof = !*c->iterator;
812   }
813   return SQLITE_OK;
814 }
815 
Next(sqlite3_vtab_cursor * cursor)816 int DbSqliteModule::Next(sqlite3_vtab_cursor* cursor) {
817   auto* c = GetCursor(cursor);
818   if (c->mode == Cursor::Mode::kSingleRow) {
819     c->eof = true;
820   } else {
821     c->eof = !++*c->iterator;
822   }
823   return SQLITE_OK;
824 }
825 
Eof(sqlite3_vtab_cursor * cursor)826 int DbSqliteModule::Eof(sqlite3_vtab_cursor* cursor) {
827   return GetCursor(cursor)->eof;
828 }
829 
Column(sqlite3_vtab_cursor * cursor,sqlite3_context * ctx,int N)830 int DbSqliteModule::Column(sqlite3_vtab_cursor* cursor,
831                            sqlite3_context* ctx,
832                            int N) {
833   Cursor* c = GetCursor(cursor);
834   auto idx = static_cast<uint32_t>(N);
835   const auto* source_table =
836       c->sorted_cache_table ? &*c->sorted_cache_table : c->upstream_table;
837   SqlValue value = c->mode == Cursor::Mode::kSingleRow
838                        ? source_table->columns()[idx].Get(*c->single_row)
839                        : c->iterator->Get(idx);
840 
841   // We can say kSqliteStatic for strings because all strings are expected
842   // to come from the string pool. Thus they will be valid for the lifetime
843   // of trace processor. Similarily, for bytes, we can also use
844   // kSqliteStatic because for our iterator will hold onto the pointer as
845   // long as we don't call Next(). However, that only happens when Next() is
846   // called on the Cursor itself, at which point SQLite no longer cares
847   // about the bytes pointer.
848   sqlite::utils::ReportSqlValue(ctx, value, sqlite::utils::kSqliteStatic,
849                                 sqlite::utils::kSqliteStatic);
850   return SQLITE_OK;
851 }
852 
Rowid(sqlite3_vtab_cursor *,sqlite_int64 *)853 int DbSqliteModule::Rowid(sqlite3_vtab_cursor*, sqlite_int64*) {
854   return SQLITE_ERROR;
855 }
856 
EstimateCost(const Table::Schema & schema,uint32_t row_count,sqlite3_index_info * info,const std::vector<int> & cs_idxes,const std::vector<int> & ob_idxes)857 DbSqliteModule::QueryCost DbSqliteModule::EstimateCost(
858     const Table::Schema& schema,
859     uint32_t row_count,
860     sqlite3_index_info* info,
861     const std::vector<int>& cs_idxes,
862     const std::vector<int>& ob_idxes) {
863   // Currently our cost estimation algorithm is quite simplistic but is good
864   // enough for the simplest cases.
865   // TODO(lalitm): replace hardcoded constants with either more heuristics
866   // based on the exact type of constraint or profiling the queries
867   // themselves.
868 
869   // We estimate the fixed cost of set-up and tear-down of a query in terms of
870   // the number of rows scanned.
871   constexpr double kFixedQueryCost = 1000.0;
872 
873   // Setup the variables for estimating the number of rows we will have at the
874   // end of filtering. Note that |current_row_count| should always be at least
875   // 1 unless we are absolutely certain that we will return no rows as
876   // otherwise SQLite can make some bad choices.
877   uint32_t current_row_count = row_count;
878 
879   // If the table is empty, any constraint set only pays the fixed cost. Also
880   // we can return 0 as the row count as we are certain that we will return no
881   // rows.
882   if (current_row_count == 0) {
883     return QueryCost{kFixedQueryCost, 0};
884   }
885 
886   // Setup the variables for estimating the cost of filtering.
887   double filter_cost = 0.0;
888   for (int i : cs_idxes) {
889     if (current_row_count < 2) {
890       break;
891     }
892     const auto& c = info->aConstraint[i];
893     PERFETTO_DCHECK(c.usable);
894     PERFETTO_DCHECK(info->aConstraintUsage[i].omit);
895     PERFETTO_DCHECK(info->aConstraintUsage[i].argvIndex > 0);
896     const auto& col_schema = schema.columns[static_cast<uint32_t>(c.iColumn)];
897     if (sqlite::utils::IsOpEq(c.op) && col_schema.is_id) {
898       // If we have an id equality constraint, we can very efficiently filter
899       // down to a single row in C++. However, if we're joining with another
900       // table, SQLite will do this once per row which can be extremely
901       // expensive because of all the virtual table (which is implemented
902       // using virtual function calls) machinery. Indicate this by saying that
903       // an entire filter call is ~10x the cost of iterating a single row.
904       filter_cost += 10;
905       current_row_count = 1;
906     } else if (sqlite::utils::IsOpEq(c.op)) {
907       // If there is only a single equality constraint, we have special logic
908       // to sort by that column and then binary search if we see the
909       // constraint set often. Model this by dividing by the log of the number
910       // of rows as a good approximation. Otherwise, we'll need to do a full
911       // table scan. Alternatively, if the column is sorted, we can use the
912       // same binary search logic so we have the same low cost (even
913       // better because we don't // have to sort at all).
914       filter_cost += cs_idxes.size() == 1 || col_schema.is_sorted
915                          ? log2(current_row_count)
916                          : current_row_count;
917 
918       // As an extremely rough heuristic, assume that an equalty constraint
919       // will cut down the number of rows by approximately double log of the
920       // number of rows.
921       double estimated_rows = current_row_count / (2 * log2(current_row_count));
922       current_row_count = std::max(static_cast<uint32_t>(estimated_rows), 1u);
923     } else if (col_schema.is_sorted &&
924                (sqlite::utils::IsOpLe(c.op) || sqlite::utils::IsOpLt(c.op) ||
925                 sqlite::utils::IsOpGt(c.op) || sqlite::utils::IsOpGe(c.op))) {
926       // On a sorted column, if we see any partition constraints, we can do
927       // this filter very efficiently. Model this using the log of the  number
928       // of rows as a good approximation.
929       filter_cost += log2(current_row_count);
930 
931       // As an extremely rough heuristic, assume that an partition constraint
932       // will cut down the number of rows by approximately double log of the
933       // number of rows.
934       double estimated_rows = current_row_count / (2 * log2(current_row_count));
935       current_row_count = std::max(static_cast<uint32_t>(estimated_rows), 1u);
936     } else {
937       // Otherwise, we will need to do a full table scan and we estimate we
938       // will maybe (at best) halve the number of rows.
939       filter_cost += current_row_count;
940       current_row_count = std::max(current_row_count / 2u, 1u);
941     }
942   }
943 
944   // Now, to figure out the cost of sorting, multiply the final row count
945   // by |qc.order_by().size()| * log(row count). This should act as a crude
946   // estimation of the cost.
947   double sort_cost =
948       static_cast<double>(static_cast<uint32_t>(ob_idxes.size()) *
949                           current_row_count) *
950       log2(current_row_count);
951 
952   // The cost of iterating rows is more expensive than just filtering the rows
953   // so multiply by an appropriate factor.
954   double iteration_cost = current_row_count * 2.0;
955 
956   // To get the final cost, add up all the individual components.
957   double final_cost =
958       kFixedQueryCost + filter_cost + sort_cost + iteration_cost;
959   return QueryCost{final_cost, current_row_count};
960 }
961 
State(Table * _table,Table::Schema _schema)962 DbSqliteModule::State::State(Table* _table, Table::Schema _schema)
963     : State(TableComputation::kStatic, std::move(_schema)) {
964   static_table = _table;
965 }
966 
State(std::unique_ptr<RuntimeTable> _table)967 DbSqliteModule::State::State(std::unique_ptr<RuntimeTable> _table)
968     : State(TableComputation::kRuntime, _table->schema()) {
969   runtime_table = std::move(_table);
970 }
971 
State(std::unique_ptr<StaticTableFunction> _static_function)972 DbSqliteModule::State::State(
973     std::unique_ptr<StaticTableFunction> _static_function)
974     : State(TableComputation::kTableFunction,
975             _static_function->CreateSchema()) {
976   static_table_function = std::move(_static_function);
977   for (const auto& c : schema.columns) {
978     argument_count += c.is_hidden;
979   }
980 }
981 
State(TableComputation _computation,Table::Schema _schema)982 DbSqliteModule::State::State(TableComputation _computation,
983                              Table::Schema _schema)
984     : computation(_computation), schema(std::move(_schema)) {}
985 
986 }  // namespace perfetto::trace_processor
987