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