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