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
FreeSqliteString(char * resource)32 int QueryConstraints::FreeSqliteString(char* resource) {
33 sqlite3_free(resource);
34 return 0;
35 }
36
operator ==(const QueryConstraints & other) const37 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
AddConstraint(int column,unsigned char op)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
AddOrderBy(int column,unsigned char desc)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
ToNewSqlite3String() const74 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
FromString(const char * idxStr)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