| /* |
| * Copyright (C) 2019 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "src/trace_processor/metadata_table.h" |
| #include "src/trace_processor/sqlite/sqlite_utils.h" |
| #include "src/trace_processor/storage_columns.h" |
| #include "src/trace_processor/storage_schema.h" |
| |
| namespace perfetto { |
| namespace trace_processor { |
| |
| MetadataTable::MetadataTable(sqlite3*, const TraceStorage* storage) |
| : storage_(storage) {} |
| |
| void MetadataTable::RegisterTable(sqlite3* db, const TraceStorage* storage) { |
| SqliteTable::Register<MetadataTable>(db, storage, "metadata"); |
| } |
| |
| StorageSchema MetadataTable::CreateStorageSchema() { |
| return StorageSchema::Builder() |
| .AddColumn<StringColumn<MetadataKeyNameAccessor>>( |
| "name", &storage_->metadata().keys()) |
| .AddColumn<StringColumn<MetadataKeyTypeAccessor>>( |
| "key_type", &storage_->metadata().keys()) |
| .AddColumn<ValueColumn>("int_value", Variadic::Type::kInt, storage_) |
| .AddColumn<ValueColumn>("str_value", Variadic::Type::kString, storage_) |
| .Build({"name"}); |
| } |
| |
| uint32_t MetadataTable::RowCount() { |
| return static_cast<uint32_t>(storage_->metadata().keys().size()); |
| } |
| |
| int MetadataTable::BestIndex(const QueryConstraints&, BestIndexInfo*) { |
| return SQLITE_OK; |
| } |
| |
| MetadataTable::MetadataKeyNameAccessor::MetadataKeyNameAccessor( |
| const std::deque<metadata::KeyIDs>* keys) |
| : keys_(keys) {} |
| |
| MetadataTable::MetadataKeyNameAccessor::~MetadataKeyNameAccessor() = default; |
| |
| MetadataTable::MetadataKeyTypeAccessor::MetadataKeyTypeAccessor( |
| const std::deque<metadata::KeyIDs>* keys) |
| : keys_(keys) {} |
| |
| MetadataTable::MetadataKeyTypeAccessor::~MetadataKeyTypeAccessor() = default; |
| |
| MetadataTable::ValueColumn::ValueColumn(std::string col_name, |
| Variadic::Type type, |
| const TraceStorage* storage) |
| : StorageColumn(col_name, false /* hidden */), |
| type_(type), |
| storage_(storage) { |
| PERFETTO_CHECK(type == Variadic::Type::kInt || |
| type == Variadic::Type::kString); |
| } |
| |
| void MetadataTable::ValueColumn::ReportResult(sqlite3_context* ctx, |
| uint32_t row) const { |
| const auto& metadata = storage_->metadata(); |
| auto value_type = metadata::kValueTypes[metadata.keys()[row]]; |
| if (value_type != type_) { |
| sqlite3_result_null(ctx); |
| return; |
| } |
| |
| if (value_type == Variadic::Type::kInt) { |
| sqlite_utils::ReportSqliteResult(ctx, metadata.values()[row].int_value); |
| return; |
| } |
| if (value_type == Variadic::Type::kString) { |
| const char* str = |
| storage_->GetString(metadata.values()[row].string_value).c_str(); |
| sqlite3_result_text(ctx, str, -1, sqlite_utils::kSqliteStatic); |
| return; |
| } |
| PERFETTO_FATAL("Unimplemented metadata value type."); |
| } |
| |
| MetadataTable::ValueColumn::Bounds MetadataTable::ValueColumn::BoundFilter( |
| int, |
| sqlite3_value*) const { |
| return Bounds{}; |
| } |
| |
| void MetadataTable::ValueColumn::Filter(int op, |
| sqlite3_value* value, |
| FilteredRowIndex* index) const { |
| if (type_ == Variadic::Type::kInt) { |
| bool op_is_null = sqlite_utils::IsOpIsNull(op); |
| auto predicate = sqlite_utils::CreateNumericPredicate<int64_t>(op, value); |
| index->FilterRows( |
| [this, predicate, op_is_null](uint32_t row) PERFETTO_ALWAYS_INLINE { |
| const auto& arg = storage_->metadata().values()[row]; |
| return arg.type == type_ ? predicate(arg.int_value) : op_is_null; |
| }); |
| return; |
| } |
| if (type_ == Variadic::Type::kString) { |
| auto predicate = sqlite_utils::CreateStringPredicate(op, value); |
| index->FilterRows([this, &predicate](uint32_t row) PERFETTO_ALWAYS_INLINE { |
| const auto& arg = storage_->metadata().values()[row]; |
| return arg.type == type_ |
| ? predicate(storage_->GetString(arg.string_value).c_str()) |
| : predicate(nullptr); |
| }); |
| return; |
| } |
| PERFETTO_FATAL("Unimplemented metadata value type."); |
| } |
| |
| MetadataTable::ValueColumn::Comparator MetadataTable::ValueColumn::Sort( |
| const QueryConstraints::OrderBy& ob) const { |
| if (ob.desc) { |
| return [this](uint32_t f, uint32_t s) { return -CompareRefsAsc(f, s); }; |
| } |
| return [this](uint32_t f, uint32_t s) { return CompareRefsAsc(f, s); }; |
| } |
| |
| int MetadataTable::ValueColumn::CompareRefsAsc(uint32_t f, uint32_t s) const { |
| const auto& arg_f = storage_->metadata().values()[f]; |
| const auto& arg_s = storage_->metadata().values()[s]; |
| |
| if (arg_f.type == type_ && arg_s.type == type_) { |
| if (type_ == Variadic::Type::kInt) { |
| return sqlite_utils::CompareValuesAsc(arg_f.int_value, arg_s.int_value); |
| } |
| if (type_ == Variadic::Type::kString) { |
| const auto& f_str = storage_->GetString(arg_f.string_value); |
| const auto& s_str = storage_->GetString(arg_s.string_value); |
| return sqlite_utils::CompareValuesAsc(f_str, s_str); |
| } |
| PERFETTO_FATAL("Unimplemented metadata value type."); |
| } else if (arg_s.type == type_) { |
| return -1; |
| } else if (arg_f.type == type_) { |
| return 1; |
| } |
| return 0; |
| } |
| |
| } // namespace trace_processor |
| } // namespace perfetto |