1 /* 2 * Copyright (C) 2018 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/query_constraints.h" 18 19 #include <sqlite3.h> 20 #include <string> 21 22 #include "perfetto/base/string_splitter.h" 23 24 namespace perfetto { 25 namespace trace_processor { 26 27 QueryConstraints::QueryConstraints() = default; 28 QueryConstraints::~QueryConstraints() = default; 29 QueryConstraints::QueryConstraints(QueryConstraints&&) noexcept = default; 30 QueryConstraints& QueryConstraints::operator=(QueryConstraints&&) = default; 31 32 int QueryConstraints::FreeSqliteString(char* resource) { 33 sqlite3_free(resource); 34 return 0; 35 } 36 37 bool QueryConstraints::operator==(const QueryConstraints& other) const { 38 if ((other.constraints().size() != constraints().size()) || 39 (other.order_by().size() != order_by().size())) { 40 return false; 41 } 42 43 for (size_t i = 0; i < constraints().size(); ++i) { 44 if ((constraints()[i].iColumn != other.constraints()[i].iColumn) || 45 (constraints()[i].op != other.constraints()[i].op)) { 46 return false; 47 } 48 } 49 50 for (size_t i = 0; i < order_by().size(); ++i) { 51 if ((order_by()[i].iColumn != other.order_by()[i].iColumn) || 52 (order_by()[i].desc != other.order_by()[i].desc)) { 53 return false; 54 } 55 } 56 57 return true; 58 } 59 60 void QueryConstraints::AddConstraint(int column, unsigned char op) { 61 Constraint c{}; 62 c.iColumn = column; 63 c.op = op; 64 constraints_.emplace_back(c); 65 } 66 67 void QueryConstraints::AddOrderBy(int column, unsigned char desc) { 68 OrderBy ob{}; 69 ob.iColumn = column; 70 ob.desc = desc; 71 order_by_.emplace_back(ob); 72 } 73 74 QueryConstraints::SqliteString QueryConstraints::ToNewSqlite3String() const { 75 std::string str_result; 76 str_result.reserve(512); 77 str_result.append("C"); 78 str_result.append(std::to_string(constraints_.size())); 79 str_result.append(","); 80 for (const auto& cs : constraints_) { 81 str_result.append(std::to_string(cs.iColumn)); 82 str_result.append(","); 83 str_result.append(std::to_string(cs.op)); 84 str_result.append(","); 85 } 86 str_result.append("O"); 87 str_result.append(std::to_string(order_by_.size())); 88 str_result.append(","); 89 for (const auto& ob : order_by_) { 90 str_result.append(std::to_string(ob.iColumn)); 91 str_result.append(","); 92 str_result.append(std::to_string(ob.desc)); 93 str_result.append(","); 94 } 95 96 // The last char is a "," so overwriting with the null terminator on purpose. 97 SqliteString result( 98 static_cast<char*>(sqlite3_malloc(static_cast<int>(str_result.size())))); 99 strncpy(result.get(), str_result.c_str(), str_result.size()); 100 (*result)[str_result.size() - 1] = '\0'; 101 102 return result; 103 } 104 105 QueryConstraints QueryConstraints::FromString(const char* idxStr) { 106 QueryConstraints qc; 107 108 base::StringSplitter splitter(std::string(idxStr), ','); 109 110 PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1); 111 // The '+ 1' skips the letter 'C' in the first token. 112 long num_constraints = strtol(splitter.cur_token() + 1, nullptr, 10); 113 for (int i = 0; i < num_constraints; ++i) { 114 PERFETTO_CHECK(splitter.Next()); 115 int col = static_cast<int>(strtol(splitter.cur_token(), nullptr, 10)); 116 PERFETTO_CHECK(splitter.Next()); 117 unsigned char op = 118 static_cast<unsigned char>(strtol(splitter.cur_token(), nullptr, 10)); 119 qc.AddConstraint(col, op); 120 } 121 122 PERFETTO_CHECK(splitter.Next() && splitter.cur_token_size() > 1); 123 // The '+ 1' skips the letter 'O' in the current token. 124 long num_order_by = strtol(splitter.cur_token() + 1, nullptr, 10); 125 for (int i = 0; i < num_order_by; ++i) { 126 PERFETTO_CHECK(splitter.Next()); 127 int col = static_cast<int>(strtol(splitter.cur_token(), nullptr, 10)); 128 PERFETTO_CHECK(splitter.Next()); 129 unsigned char desc = 130 static_cast<unsigned char>(strtol(splitter.cur_token(), nullptr, 10)); 131 qc.AddOrderBy(col, desc); 132 } 133 134 PERFETTO_DCHECK(!splitter.Next()); 135 return qc; 136 } 137 138 } // namespace trace_processor 139 } // namespace perfetto 140