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/counter_definitions_table.h" 18 19 #include <string> 20 21 #include "src/trace_processor/storage_columns.h" 22 23 namespace perfetto { 24 namespace trace_processor { 25 26 CounterDefinitionsTable::CounterDefinitionsTable(sqlite3*, 27 const TraceStorage* storage) 28 : storage_(storage) {} 29 30 void CounterDefinitionsTable::RegisterTable(sqlite3* db, 31 const TraceStorage* storage) { 32 Table::Register<CounterDefinitionsTable>(db, storage, "counter_definitions"); 33 } 34 35 StorageSchema CounterDefinitionsTable::CreateStorageSchema() { 36 const auto& cs = storage_->counter_definitions(); 37 return StorageSchema::Builder() 38 .AddGenericNumericColumn("counter_id", RowAccessor()) 39 .AddStringColumn("name", &cs.name_ids(), &storage_->string_pool()) 40 .AddNumericColumn("ref", &cs.refs()) 41 .AddStringColumn("ref_type", &cs.types(), &GetRefTypeStringMap()) 42 .Build({"counter_id"}); 43 } 44 45 uint32_t CounterDefinitionsTable::RowCount() { 46 return storage_->counter_definitions().size(); 47 } 48 49 int CounterDefinitionsTable::BestIndex(const QueryConstraints& qc, 50 BestIndexInfo* info) { 51 info->estimated_cost = EstimateCost(qc); 52 53 // Only the string columns are handled by SQLite 54 size_t name_index = schema().ColumnIndexFromName("name"); 55 size_t ref_type_index = schema().ColumnIndexFromName("ref_type"); 56 info->order_by_consumed = true; 57 for (size_t i = 0; i < qc.constraints().size(); i++) { 58 auto col = static_cast<size_t>(qc.constraints()[i].iColumn); 59 info->omit[i] = col != name_index && col != ref_type_index; 60 } 61 62 return SQLITE_OK; 63 } 64 65 uint32_t CounterDefinitionsTable::EstimateCost(const QueryConstraints& qc) { 66 // If there is a constraint on the counter id, we can efficiently filter 67 // to a single row. 68 if (HasEqConstraint(qc, "counter_id")) 69 return 1; 70 71 auto eq_name = HasEqConstraint(qc, "name"); 72 auto eq_ref = HasEqConstraint(qc, "ref"); 73 auto eq_ref_type = HasEqConstraint(qc, "ref_type"); 74 75 // If there is a constraint on all three columns, we are going to only return 76 // exaclty one row for sure so make the cost 1. 77 if (eq_name && eq_ref && eq_ref_type) 78 return 1; 79 else if (eq_name && eq_ref) 80 return 10; 81 else if (eq_name) 82 return 100; 83 return RowCount(); 84 } 85 86 } // namespace trace_processor 87 } // namespace perfetto 88